Prevent Realm from overwriting a property when updating an Object

╄→гoц情女王★ 提交于 2019-12-03 10:58:26

问题


I've setup a REST API to realm object in iOS. However I've found an issue with creating a favorite flag in my object. I've created a favorite bool, however everytime the object is updated from the API it sets the favorite to default false again. Here I want this flag to not be updated, since the favorite only is stored locally. How can I achieve 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"
    }
}

CreateOrUpdate

let pet = Pet()
pet.id = 2
pet.name = "Dog"
pet.type = "German Shephard"


try! realm.write {
    realm.add(pet, update: true)
}

回答1:


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.




回答2:


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

3. Retrieve the current value for the update

// Using the add/update method
let pet = Pet()
pet.id = 2
pet.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 method
var favorite = false
if let currentObject = realm.object(ofType: Pet.self, forPrimaryKey: 2) {
    favorite = currentObject.favorite
}

// Other properties on the pet, such as a list will remain unchanged
try! realm.write {
    realm.create(Pet.self, value: ["id": 2, "name": "Dog", "type": "German Shephard", "favorite": favorite], update: true)
}



回答3:


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.



来源:https://stackoverflow.com/questions/32891269/prevent-realm-from-overwriting-a-property-when-updating-an-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!