关于mutablecopy的使用
前段时间在使用MJExtension做模型生成时遇到属性声明成@property (nonatomic, copy) NSMutableDictionary *config;
时,在向config添加数据时报错-[__NSFrozenDictionaryM setObject:forKeyedSubscript:]: unrecognized selector sent to instance
,参考重写model的description方法时使用mj_keyValues,全局异常断点崩溃了,按照MJ大神的建议改成Strong后决解了问题。使用copy需要注意,见copy部分;
另外在做另一个项目时,使用dictionary0对其他dictionary1赋值后,修改dic1时,dic0也会跟着发生改变。见mutableCopy部分分析;
对于属性使用copy来持有:
- 在类之间进行传值、对外属性在声明内存管理时,使用copy一般会比strong安全,特别是对有可变子类的类型,如NSString、NSArray、NSDictionary等;
- 在类的实现具体部分,分类Category中添加属性(私有)时,这部分的属性在声明内存管理时可以使用strong来管理;
- 大致分析时参考:NSString NSMutableString NSArray NSMutableArray Block 分别用哪些修饰?;
- 结合上面第1、2点,在声明私有可变类型属性时(如
NSMutableArray *mList
),谨慎使用copy关键字。原因分析:类的实例在初始化时对mList近初始化self.mList = [[NSMutableArray alloc] init];
时,mList属性由于copy特性将生成的对象通过copy方法后得到一个immutable对象,在后续的使用中mList其实就是一个不可变对象,因此不能插入数据,dictionary同理。即使不在对象初始化时对mList进行初始化,在后续使用时,第一次对mList赋值时,copy同样会将赋值对象copy成一个immutable对象赋值给mList。 - 因此在声明私有可变属性时,最好使用strong关键字,他既不会受外部对象影响,也能保证他的可变形;
Mutablecopy数组、字典等集合时,具体内容的copy
在对数据做过滤的时候,希望保存一份原数据originalData,复制出来一份copyData,仅对复制数据进行过滤等操作,此时用mutableCopy进行复制操作。在copy完成后,对copyData进行过滤时,很可能因为originalData中多层次数据结构的原因,mutableCopy后,copyData后originalData在深层次上内容仍然是使用同一个内存地址的内容,因此在使用时最好注意dic内部数据是否已经被copy到。