因此,我在我的“主”数组持有类的getter方法中使用以下内容:
[[NSMutableArray alloc] initWithArray:masterArray copyItems:YES];
然而,这似乎会使得所有内部的字典都是不可变的。我该如何避免这种情况?
我觉得我在这里漏掉了什么。任何帮助将不胜感激!
[[NSMutableArray alloc] initWithArray:masterArray copyItems:YES];
然而,这似乎会使得所有内部的字典都是不可变的。我该如何避免这种情况?
我觉得我在这里漏掉了什么。任何帮助将不胜感激!
你可以采用另一种方法,使用CFPropertyListCreateDeepCopy()函数(在CoreFoundation框架中),将mutabilityOption参数设置为kCFPropertyListMutableContainers。代码如下:
NSMutableArray* originalArray;
NSMutableArray* newArray;
newArray = (NSMutableArray*)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFPropertyListRef)originalArray, kCFPropertyListMutableContainers);
这将不仅创建字典的可变副本,还将递归地创建其中包含的任何东西的可变副本。请注意,这只有在您的字典数组中只包含有效的属性列表对象(数组,数字,日期,数据,字符串和字典)时才会起作用,因此在特定情况下可能或可能不适用。
复制一个数组将创建一个数组对象的副本,其中包含对原始内容对象的引用(适当保留)。
根据文档,-initWithArray:copyItems:
会使用原始数组中的副本来初始化新数组。这个副本是通过向原始内容对象发送 -copyWithZone:
来创建的,在可变对象的情况下会创建一个不可变的副本。
如果您需要不同的行为(例如内容对象的可变副本或深层副本),则必须编写自己的便捷函数/方法来实现。
mutableCopy
,并向每个副本发送autorelease
。但那是一个肮脏的、不好的技巧,所以不要这样做。事实上,你可能在第一时间就不应该这么做。NSCopying
,而不需要担心可变性与不可变性,因为你的真正模型类中可能不会有可变性区分。(我不知道其他人怎么想,但在我的模型类中从未做出过这样的区分。)然后你只需使用现有的NSArray initWithArray:copyItems:
方法即可。关于-initWithArray:copyItems
,Jim是正确的,它会向每个元素发送一个-copyWithZone:
消息。如果要获得数组元素的可变副本,您需要向每个元素发送-mutableCopyWithZone:
(或者为了简洁起见,只需使用-mutableCopy
)。这很简单:
NSMutableArray *masterArray = ...
NSMutableArray *clone = [NSMutableArray arrayWithCapacity:[masterArray count]];
for (id anObject in masterArray)
[clone addObject:[anObject mutableCopy]]; // OR [clone addObject:anObject];
NSMutableArray *masterArray = ...
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:masterArray];
NSMutableArray *clone = [NSKeyedUnarchiver unarchiveObjectWithData:data];
基本上,这将所有内容转换为原始数据字节,然后重新组合成一组新的对象。为了使其正常工作,字典中的所有对象都必须符合NSCoding协议。这可能需要一些操作,但这是一种优雅的通用方法,可确保对象唯一性。当然,这肯定会带来一定的性能成本,但如果您绝对需要保证没有任何副作用,那么它应该可以胜任。