Meep
Meep

Reputation: 531

Realm and Swift - parameters to pass for the model to be updated

In the beginning of the project, Realm is great and easy to work and the project is getting complicated so I need to figure out how to decouple the realm layer and uiviewcontroller.

There is some awkwardness by writing a realm object with parameters. I would like to have object updated with the parameter then pass to the realm database to update object in (table?). Initially, I have a function to write a realm object by -

func createOrUpdateNote(note : Note, body : String, textSize : Float, toggleColor : Int) {
        let realm = try! Realm()
        do {
            try realm.write {
                if note.id == -1 {
                    note.id = NoteManager.createNotePrimaryId()
                }
                note.body = body
                note.textSize = textSize
                note.toggleColor = toggleColor
                realm.add(note, update: true)
            }
        }
        catch {
            print(error.localizedDescription)
        }
    }

I would like to have like this function. Hope it clears up my question here.

func createOrUpdateNote(note : Note) {
            let realm = try! Realm()
            do {
                try realm.write {
                    realm.add(note, update: true)
                }
            }
            catch {
                print(error.localizedDescription)
            }
        }

Now I have another viewcontroller to update the object with their preference of using language below.

func createOrUpdateNote(note : Note, language : String) {
            let realm = try! Realm()
            do {
                try realm.write {
                    if note.id == -1 {
                        note.id = NoteManager.createNotePrimaryId()
                    }
                    note.language = language
                    realm.add(note, update: true)
                }
            }
            catch {
                print(error.localizedDescription)
            }
        }

There will be two similar functions (dup functions) in database layer and that will not work well when the project is getting more features so I'm stepping back to see if I can redesign the create or update the object approach.

I googled and there are several solutions like making UI object and copy the ui values over to the realm objects each time I do CRUD, create object with internal realm object (1 to 1 mapping), or I'm thinking about partial update but not sure how can I approach this situation. Ideally, I would prefer only object to carry over to be updated. Any suggestions?

Upvotes: 2

Views: 2932

Answers (1)

Jay
Jay

Reputation: 35648

If you have an existing (managed) Realm object, its properties can only be modified within a write block. However, ANY of it's properties can be modified and you really only need one block 'style' to do it.

So for example, if we have a Note Realm object

Note: Object {
   @objc dynamic var body = ""
   @objc dynamic var textSize = 12
   @objc dynamic var language = "English"
}

any time we have access to that Note, we can modify it's properties within a write closure. Let's say a user is editing an existing note and changes the body, then clicks Save.

let realm = try Realm()

try! realm.write {
     myNote.body = updatedBodyText
     realm.add(myNote, update: true)
}

or they change the text size

let realm = try Realm()

try! realm.write {
     myNote.textSize = updatedTextSize
     realm.add(myNote, update: true)
}

Notice that those blocks are identical, other than which property is updated. The key is to hang on to a reference to the note when loaded, so you can then modify it's properties in a write block when saving.

There's no problem having multiple write blocks depending on what property you're saving. It really depends on your use case but that's common practice.

Generically speaking it could also be rolled into one function, something like this:

func saveMyNote(myNote: NoteClass, updatedData: String, fieldType: NoteFieldTypes) {

   try! realm.write {
      switch fieldType:
      case .body:
         myNote.body = updatedData
      case .language:
         myNote.language = updatedData
      etc etc

      realm.add(myNote, update: true)
}

You could also extend the class or a variety of other solutions. In general the write code is so small I would just use it wherever you need to update an objects fields.

Upvotes: 1

Related Questions