Search code examples
iosdatabase-designswift3realmrealm-mobile-platform

Realm "update" issue


I have a Realm model called Person:

class Person: Object {

static let sharedInstance = Person()

dynamic var tableId:Int = 1453
dynamic var verificationCode = ""
dynamic var userId = ""
dynamic var phoneNumber = ""
dynamic var userName = ""
dynamic var registered: Bool = false
dynamic var userPhoto: NSData = NSData()

override class func primaryKey() -> String? {
    return "tableId"
}

func save(isUpdate: Bool) {
    do {
        let realm = try Realm()
        try realm.write {
            realm.add(self, update: isUpdate)
        }
    } catch let error as NSError {
        fatalError(error.localizedDescription)
    }
}

So first i save some values:

func addTask(){
personObject.tableId = 1453
personObject.phoneNumber = "+60176336055"
personObject.verificationCode = "112"
personObject.userId = "r456666vhffg547567bg55"
personObject.registered = false
personObject.save(isUpdate: false)
}

and later i use "update" method to add values for other columns:

func update() {
personObject.tableId = 1453
personObject.registered = true
personObject.userName = self.usernameText.text!
if self.chosenImage != nil, let imageData = self.chosenImage.jpeg(.lowest) as NSData? {
   personObject.userPhoto = imageData
}
personObject.save(isUpdate: true)
}

But after i update my model, it will set old values empty which i didnt want to update but retain them. Is there any way to update the row without passing all existing values again? I appreciate any kind of help. Thank you.


Solution

  • Instead of inserting an unmanaged copy with all fields set properly, you can query the object by id (if exists) and modify its properties inside a transaction. If it doesn't exist, then an unmanaged copy should be added to Realm first.

    autoreleasepool {
        let realm = try! Realm()
        try! realm.write {
            let person = realm.objects(Person.self).filter(NSPredicate(format: "tableId = %@", tableId).first;
            person.userName = usernameText;
        }
    }