Objective-C Overwrite only non-nil properties

余生长醉 提交于 2020-01-05 10:29:13

问题


Let's say I have a class Car, with the following property scheme:

@interface Car : NSObject

@property int carID;
@property Driver *driver;
@property NSString *brandName;
...

@end

Now, I have a dictionary of Car instances, and whenever I download a new instance from my server, I overwrite with carDictionary[@(newCar.carID)] = newCar; to keep my instances updated. The only issue is that sometimes my instances are downloaded with some properties not filled out.

When I download a new instance, is there a way to only overwrite using the non-nil properties I download and leave the nil properties alone? Obviously, I could manually set each property, but I don't want to have to change this every time I add a new property.


回答1:


Let's say you get a dictionary as a result of your web service call. Now you want to use that dictionary to instantiate or update a Car object, where an update does not overwrite existing valid data with nil data from the dictionary.

Assume the property names in your class correspond to the key names in your dictionary.

Here's an approach:

  1. Get the existing Car object for the current dictionary from the carDictionary:

    Car *currentCar = carDictionary[@(newCar.carID)];

  2. If no car is returned, instantiate a new one:

      if (currentCar == nil) {
        currentCar = [[Car alloc] init];
       }
    
  3. Assign all the values from your downloaded dictionary to the car instance:

    [currentCar setValuesForKeysWithDictionary:yourDownloadedDictionary];

    That method will map the keys from the dictionary with the keys in your Car instance. The dictionary keys need to match the keys in your class, and often it's worth just using the same names so you get to use this convenient method.

    It will throw an exception if there is a new key added to your web service dictionary that does not correlate to a key/property in your class. This would break your app if your web service started giving out new keys while some users had outdated versions of your app. To solve that..

  4. Override - (void)setValue:(id)value forUndefinedKey:(NSString *)key; so it does nothing, other than perhaps log out the fact that a key was attempted to be set but your class doesn't implement that key/property.

Then you have the problem of "Don't set nil values". You can tell your class not to overwrite existing content with nil values by...

  1. Override -(void)setValue:forKey:

    -(void)setValue:(id)value forKey:(NSString *)key {
       if (value != nil) {
         [super setValue:value forKey:key];
    } else {
             NSLog(@"Not changing %@ because its value is nil.", key);
       }
      }
    

It's a bit more work in setting up the class, but it gives you future proofing for when your web service expands its returned attribute set.




回答2:


There's no built-in way in Objective-C to do this. That said, I think this is how I would approach it.

I would start by adding a method on Car which updated it with the new information:

-(void)updateWithNewCarInfo(Car *)newCar

The straightforward way is to just manually copy the properties yourself. But if you want to do a bit of future-proofing, you can use Objective-C's introspection capabilities to get a list of the properties on your class and iterate through them yourself. This question has some pointers on how to do that. You'll need to implement your own logic as to which properties to overwrite when, though.




回答3:


Since there is already a Car object in carDictionary at this spot, instead of wantonly replacing it, write a Car method updateWithValuesFromCar: that takes another Car and does what you want done, and call that.

I would start with an array of property names @["carID", "driver", "brandName"] (and so on) and cycle through that, using key-value coding to check each incoming property value and decide whether to replace my own corresponding property value.



来源:https://stackoverflow.com/questions/27625729/objective-c-overwrite-only-non-nil-properties

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