OC中copy修飾@property
1.copy修飾字符串,可以防止外界修改內(nèi)部的數(shù)據(jù)
@interfaceStudent:NSObject@property(nonatomic,strong)NSString*name;@end
NSMutableString*temp=[[NSMutableString alloc]initWithFormat:@"lwl"];Student*stu=[[Student alloc]init];stu.name=temp;[temp appendString:@" test"];NSLog(@"name = %@",stu.name);
首先我們創(chuàng)建了一個(gè)Student類(lèi),并聲明了一個(gè)name屬性,修飾符為strong。在代碼二中,定義了一個(gè)變量temp可變字符串,并創(chuàng)建了stu實(shí)例。把temp字符串賦值給stu中的name屬性。最后temp字符串追加@“test”,最后打印出來(lái)的stu的name也會(huì)追加test;
2019-01-2714:50:25.484899+0800CopyUserProperty[8486:938202]Hello,World!2019-01-2714:50:25.485079+0800CopyUserProperty[8486:938202]name=lwl testProgram endedwithexit code:0
**解決辦法**
只需要將Student中的name屬性修飾的strong變成copy即可
@interfaceStudent:NSObject@property(nonatomic,copy)NSString*name;@end
2019-01-2715:12:39.131612+0800CopyUserProperty[9016:1066999]Hello,World!2019-01-2715:12:39.131878+0800CopyUserProperty[9016:1066999]name=lwlProgram endedwithexit code:0
**分析原因**
如果修飾符為strong,在將temp賦值給stu的name的時(shí)候,temp指向的對(duì)象會(huì)在引用計(jì)數(shù)(retaincount)會(huì)加1,相單于兩個(gè)變量同時(shí)指向了同一個(gè)對(duì)象,修改其中一個(gè)另外一個(gè)肯定會(huì)變換。如果修飾符為copy,在將temp賦值給stu的name的時(shí)候,會(huì)重新拷貝一個(gè)對(duì)象放在堆中,temp指向的對(duì)象的引用計(jì)數(shù)(retaincount)不會(huì)加1,temp和stu的name指向不同的對(duì)象。是深拷貝。
2.copy修飾block
block默認(rèn)存儲(chǔ)在棧中,棧中的block訪問(wèn)到外界的對(duì)象時(shí),不會(huì)進(jìn)行相應(yīng)的retain操作;如果block在堆中(Block_copy宏可以將block轉(zhuǎn)移到堆中),在訪問(wèn)外界的對(duì)象時(shí),會(huì)進(jìn)行相應(yīng)的retain操作。
Student*stu=[[Student alloc]init];NSLog(@"retainCount = %lu",[stu retainCount]);void(^myBlock)(int)=^(int age){NSLog(@"num = %@",stu);};myBlock(3);Block_copy(myBlock);NSLog(@"retainCount = %lu",[stu retainCount]);
Student類(lèi)新增block屬性
typedefvoid(^myBlock)(void);@interfaceStudent:NSObject@property(nonatomic,assign)myBlock pBlock;@property(nonatomic,copy)NSString*name;@end
Dog*d=[[Dog alloc]init];Student*stu=[[Student alloc]init];stu.pBlock=^{NSLog(@"d = %@",d);};[d release];stu.pBlock();[stu release];
在stu對(duì)象中的block中訪問(wèn)到d對(duì)象,因?yàn)閎lock修飾的屬性是assgin,block保存在棧中,所以對(duì)d對(duì)象的引用計(jì)數(shù)(retaincount)不會(huì)加1,d對(duì)象釋放之后,stu對(duì)用了block就會(huì)訪問(wèn)到僵尸對(duì)象,導(dǎo)致程序崩潰。
**解決方法**
typedefvoid(^myBlock)(void);@interfaceStudent:NSObject*注意:如果是block使用copy并不是拷貝,而是轉(zhuǎn)移*@property(nonatomic,copy)myBlock pBlock;@property(nonatomic,copy)NSString*name;@end
將block修飾符變?yōu)閏opy的時(shí)候,block會(huì)被轉(zhuǎn)移到堆中,會(huì)對(duì)其引用的對(duì)象增加引用計(jì)數(shù)。
3.copy修飾block的循環(huán)引用問(wèn)題
2019-01-2715:51:57.716059+0800CopyUserProperty[10115:1259494]d=<Dog:0x1005168e0>2019-01-2715:51:57.716220+0800CopyUserProperty[10115:1259494]-[Student dealloc]Program endedwithexit code:0
上面的代碼中Student對(duì)象可以釋放,但dog對(duì)象沒(méi)有釋放。
**解除方法**
只需要在block使用的對(duì)象前面加上__block修飾
__block Dog*d=[[Dog alloc]init];Student*stu=[[Student alloc]init];stu.pBlock=^{NSLog(@"d = %@",d);};[d release];stu.pBlock();[stu release];
2019-01-2716:04:59.728277+0800CopyUserProperty[10441:1288724]-[Dog dealloc]2019-01-2716:04:59.728615+0800CopyUserProperty[10441:1288724]d=<Dog:0x100682b30>2019-01-2716:04:59.728632+0800CopyUserProperty[10441:1288724]-[Student dealloc]Program endedwithexit code:0