iOS -- distinguish an NSDictionary from an NSMutableDictiona



我有以下代码片段:

NSString* value = @"value";
NSString* key = @"key";
NSMutableDictionary* foo = [NSMutableDictionary dictionary];
NSDictionary* bar = [NSDictionary dictionary];
NSAssert([bar isKindOfClass: [NSMutableDictionary class]], @"");   // passes the assert as both are NSCFDictionary;
NSAssert([bar respondsToSelector: @selector(setValue:forKey:)], @"");   // passes the assert because it NSCFDictionary does respond to the selector
[foo setValue:value forKey:key];   // no problem, foo is mutable
[bar setValue:value forKey:key];   // crash

所以,如果我有一个对象是NSDictionaryNSMutableDictionary,缺少try块(我宁愿避免),我该如何区分呢?

老实说,如果没有@try块,就无法轻易区分。标准做法如下:

  • 如果你想检查它是否是可变的,以避免有人传递给你一个意外的可变对象,然后从你下面把它变出来,copy字典。如果它真的是不可变的,那么框架会将其优化为retain。如果它真的是可变的,那么您可能无论如何都想要一个副本
  • 如果您需要一个可变字典,请声明您的方法参数需要一个。就这么简单
  • 一般来说,要相信人们不会试图变异对象,除非明确告知它们是可变的
NSAssert([bar isMemberOfClass: [NSMutableDictionary class]], @"");

实际上很简单,您所需要做的就是针对类的成员进行测试,如下所示:

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

isKindOfClass和isMemberOfClass 之间的iPhone SDK差异

如果您需要保证字典是可变的,您应该:

  • 如果您是初始化它的人,请将它创建为可变的
  • 使用-[NSDictionary variableCopy]方法将其转换为可变实例,例如,如果您正在调用返回NSDictionary的API。请注意,mutableCopy会增加保留计数;如果使用手动引用计数,则需要释放此实例

在尝试修改NSDictionary的键和/或值之前确定它是否是可变的,可以被视为代码气味的一个例子,表明还有一个更深层次的问题需要解决。换句话说,您应该始终知道给定的字典实例是NSDictionary还是NSMutableDictionary。在这一点上,守则应该是明确的。

如果你真的不在乎它是否是可变的,但无论如何都想变异它,你可以试试这个:

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]);

我最终使用了@try-catch,但它只触发一次。所以它像一样工作

NSMutableDictionary *valuesByIdMutable = (id)self.valuesById;
simplest_block block = ^{
    [valuesByIdMutable setObject:obj forKey:key];
};
@try {
    block();
} @catch (NSException *exception) {
    self.valuesById = valuesByIdMutable = [valuesByIdMutable mutableCopy];
    block();
}

相关内容

最新更新