Prevent Realm from overwriting a property when updating an Object Prevent Realm from overwriting a property when updating an Object ios ios

Prevent Realm from overwriting a property when updating an Object


There are two ways to solve this:

1. Use an Ignored Property:

You can tell Realm that a certain property should not be persisted. To prevent that your favorite property will be persisted by Realm you have to do this:

class Pet: Object{    dynamic var id: Int = 1    dynamic var title: String = ""    dynamic var type: String = ""    dynamic var favorite: Bool = false    override class func primaryKey() -> String {        return "id"    }    override static func ignoredProperties() -> [String] {       return ["favorite"]   }}

or you could

2. Do a partial update

Or you could tell Realm explicitly which properties should be updated when you update your Pet object:

try! realm.write {  realm.create(Pet.self, value: ["id": 2, "name": "Dog", "type": "German Shepard"], update: true)}

This way the favorite property will not be changed.

Conclusion

There is one big difference between the two approaches:

Ignored Property: Realm won't store the favorite property at all. It is your responsibility to keep track of them.

Partial Update: Realm will store the 'favorite' property, but it won't be updated.

I suppose that the partial updates are what you need for your purpose.


If you want to be more explicit, there is third option:

3. Retrieve the current value for the update

// Using the add/update methodlet pet = Pet()pet.id = 2pet.name = "Dog"pet.type = "German Shephard"if let currentObject = realm.object(ofType: Pet.self, forPrimaryKey: 2) {    pet.favorite = currentObject.favorite}try! realm.write {    realm.add(pet, update: true)}// Using the create/update methodvar favorite = falseif let currentObject = realm.object(ofType: Pet.self, forPrimaryKey: 2) {    favorite = currentObject.favorite}// Other properties on the pet, such as a list will remain unchangedtry! realm.write {    realm.create(Pet.self, value: ["id": 2, "name": "Dog", "type": "German Shephard", "favorite": favorite], update: true)}


4. NSUserDefaults (or any other data store, really)

I ran into the same issue and I opted for the other, more traditional option of saving things to another data store (NSUserDefaults). In my case, I was storing the last time a user viewed an item and storing this data in NSUserDefaults felt appropriate. I did something like the following:

First, define a unique key for the object you are storing (self here is the model object being viewed and rendered):

- (NSString *)lastViewedDateKey {    // Note each item gets a unique key with <className>_<itemId> guaranteeing us uniqueness    return [NSString stringWithFormat:@"%@_%ld", self.class.className, (long)self.itemId];}

Then, when a user views the item, set the key to:

- (void)setLastViewedToNow {    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];    [userDefaults setObject:[NSDate date] forKey:self.lastViewedDateKey];    [userDefaults synchronize];}

Later, I use it like this:

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];NSDate *createdOnDate = <passed in from elsewhere>;NSDate *lastViewedDate = [userDefaults objectForKey:self.lastViewedDateKey];if (!lastViewedDate || [createdOnDate compare:lastViewedDate] == NSOrderedDescending) {    ...}

As opposed to the above solutions:1. There is no data persistence.2. This creates yet another place where one has to define the properties of an object and will likely lead to errors if one forgets to update this list every time a new property gets added.3. If you are doing any large batch updates, going back through every object is not really practical and will certainly cause pain down the road.

I hope this gives someone another option if they need it.