Prevent Realm from overwriting a property when updating an Object

前端 未结 3 1197
余生分开走
余生分开走 2021-02-05 04:54

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 obje

相关标签:
3条回答
  • 2021-02-05 05:39

    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.

    0 讨论(0)
  • 2021-02-05 05:40

    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.

    0 讨论(0)
  • 2021-02-05 05:41

    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)
    }
    
    0 讨论(0)
提交回复
热议问题