iOS — distinguish an NSDictionary from an NSMutableDictionary?

时光怂恿深爱的人放手 提交于 2019-12-01 23:32:44
NeverBe
NSAssert([bar isMemberOfClass: [NSMutableDictionary class]], @"");

Honestly, you can't easily tell the difference without a @try block. Standard practice is as follows:

  • If you want to check whether it's mutable in order to avoid someone passing you an unexpectedly mutable object and then mutating it out from under you, copy the dictionary. If it's really non-mutable, the frameworks will optimize that into a retain. If it really was mutable, then you probably wanted a copy anyway.
  • If you need a mutable dictionary, declare your method parameters to require one. Simple as that.
  • In general, trust that people won't try to mutate objects unless specifically told they were mutable.
Emil

It's pretty simple actually, all you need to do is test against the member of the class, like this:

if ([bar isMemberOfClass:[NSMutableDictionary class]]){
    [bar setValue:value forKey: key];
}

iPhone SDK difference between isKindOfClass and isMemberOfClass

If you need to guarantee that a dictionary is mutable, you should:

  • create it as mutable if you are the one initializing it
  • turn it into a mutable instance with the -[NSDictionary mutableCopy] method, for example if you're calling an API that returns an NSDictionary. Note that mutableCopy increments the retain count; you need to release this instance if you are using manual reference counting.

Determining whether an NSDictionary is mutable before attempting to modify its keys and/or values can be considered an example of a code smell, indicating that there's a deeper problem that should be solved. In other words, you should always know whether a given dictionary instance is NSDictionary or NSMutableDictionary. The code should be clear on that point.

If you really don't care if it's mutable, but want to mutate it anyway, you could try this:

NSString* value = @"value";
NSString* key = @"key";

NSDictionary* bar = [NSDictionary dictionary];
NSLog(@"bar desc: %@", [bar description]);
NSMutableDictionary* temp = [bar mutableCopy];
[temp setValue:value forKey:key];
bar = temp;
NSLog(@"bar desc: %@", [bar description]);

I end up using @try catch but it only fires once. So it works like this

NSMutableDictionary *valuesByIdMutable = (id)self.valuesById;

simplest_block block = ^{
    [valuesByIdMutable setObject:obj forKey:key];
};

@try {
    block();
} @catch (NSException *exception) {
    self.valuesById = valuesByIdMutable = [valuesByIdMutable mutableCopy];
    block();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!