iOS詳解assign、weak、retain、strong、copy、mutableCopy

先講講assign、retain、strong、weak

  • assign
@property (nonatomic,assign)NSMutableArray *arr;

self.arr = [NSMutableArray array];
[self.arr addObject:@"11"];

//運(yùn)行結(jié)果:
Thread 1: EXC_BAD_ACCESS 

這里會(huì)直接報(bào)內(nèi)存錯(cuò)誤,原因是因?yàn)椋琣ssign是用來修飾基本數(shù)據(jù)類型的,例如CGFloat、NSInteger、Int、float等等,因?yàn)樵贠C中assign修飾的對象引用計(jì)數(shù)不會(huì)加+1,這個(gè)對象會(huì)被立即釋放,而且在釋放之后不會(huì)置為nil,會(huì)保留對象的指針,會(huì)形成野指針,這個(gè)時(shí)候?qū)ζ浒l(fā)送消息就會(huì)崩潰,就會(huì)報(bào)壞內(nèi)存的錯(cuò)誤。

  • weak
@property (nonatomic,weak)NSMutableArray *weakArr;

self.weakArr = [NSMutableArray array];
[self.weakArr addObject:@"1"];
NSLog(@"%@",self.weakArr);


//運(yùn)行結(jié)果:
2018-09-19 16:51:47.901018+0800 Demo[1649:254177] (null)

在OC中Weak用來修飾對象的,如果用來修飾基本數(shù)據(jù)類型會(huì)報(bào)紅,用weak修飾的對象在引用完畢后會(huì)被立即置為nil 而OC向nil發(fā)送消息是不會(huì)崩潰的。
這里提一下assign和weak修飾的對象的引用計(jì)數(shù)都是不會(huì)加1的

  • retain和strong
@property (nonatomic,strong)NSMutableArray *strongArr;

self.strongArr = [NSMutableArray array];
[self.strongArr addObject:@"11"];
NSLog(@"%@",self.strongArr);

//運(yùn)行結(jié)果:
2018-09-19 16:56:57.389876+0800 Demo[1652:255035] (
    11
)

[NSMutableArray array]這句代碼可以理解為創(chuàng)造了一個(gè)對象A,此時(shí)A的引用計(jì)數(shù)為1,self.strongArr做為對象B,把A賦值給B的時(shí)候,A的引用計(jì)數(shù)加1,此時(shí)A的引用計(jì)數(shù)為2,B指向了A,然后編譯器會(huì)自動(dòng)對A進(jìn)行釋放操作(因?yàn)槭蔷植孔兞?,A的引用計(jì)數(shù)-1。在擁有B的對象不釋放的時(shí)候,A的引用計(jì)數(shù)永遠(yuǎn)不可能為0,除非你手動(dòng)釋放或者把B指向一個(gè)新的對象,這樣A永遠(yuǎn)不會(huì)被釋放,這就是所謂的強(qiáng)引用。retain是在MRC中用到的修飾詞,在ARC中便用strong代替了。retain現(xiàn)在同strong,就是指針指向值地址,同時(shí)進(jìn)行引用計(jì)數(shù)加1。

因?yàn)閏opy涉及的情況比較多,所以接下來單獨(dú)講講copy,主要分為以下幾種情況

在說copy與mutableCopy之前我們先看看官方文檔對深拷貝與淺拷貝的闡釋,如下

深拷貝:
對象拷貝 - 重新申請一片內(nèi)存保留這個(gè)對象,與原對象之間沒有半點(diǎn)關(guān)系。

淺拷貝:
指針拷貝 - 實(shí)際上相當(dāng)于引用計(jì)數(shù)+1,被拷貝的和拷貝的引用同一個(gè)對象。
接下來我們分兩個(gè)方面做測試:

  • 非集合不可變對象(copy、mutableCopy)
    NSString *str = [NSString stringWithFormat:@"111"];
    NSString *copyStr = [str copy];
    NSString *mCopyStr = [str mutableCopy];
    NSLog(@"%@ ---- %p",str,str);
    NSLog(@"%@ ---- %p",copyStr,copyStr);
    NSLog(@"%@ ---- %p",mCopyStr,mCopyStr);
    str = @"222";
    NSLog(@"%@ ---- %p",str,str);
    NSLog(@"%@ ---- %p",copyStr,copyStr);
    NSLog(@"%@ ---- %p",mCopyStr,mCopyStr);


//運(yùn)行結(jié)果:
2018-09-19 17:25:12.102270+0800 Demo[1689:260186] 111 ---- 0xa000000003131313
2018-09-19 17:25:12.102387+0800 Demo[1689:260186] 111 ---- 0xa000000003131313
2018-09-19 17:25:12.102418+0800 Demo[1689:260186] 111 ---- 0x2827aa9d0
2018-09-19 17:25:12.102445+0800 Demo[1689:260186] 222 ---- 0x100776020
2018-09-19 17:25:12.102491+0800 Demo[1689:260186] 111 ---- 0xa000000003131313
2018-09-19 17:25:12.102518+0800 Demo[1689:260186] 111 ---- 0x2827aa9d0

這里我們可以看到str和copyStr的地址是相同的,而mCopyStr是開辟了新的內(nèi)存的。在str = @"222"這句代碼后,因?yàn)閟tr是不可變的、不可被修改,所以重新初始化。而這里的copy為淺拷貝,mutableCopy為深拷貝。

  • 非集合可變對象(copy、mutableCopy)
    NSMutableString *mStr = [NSMutableString stringWithFormat:@"111"];
    NSString *copyStr = [mStr copy];
    NSString *mCopyStr = [mStr mutableCopy];
    NSLog(@"%@ ---- %p",mStr,mStr);
    NSLog(@"%@ ---- %p",copyStr,copyStr);
    NSLog(@"%@ ---- %p",mCopyStr,mCopyStr);
    [mStr appendString:@",222"];
    NSLog(@"%@ ---- %p",mStr,mStr);
    NSLog(@"%@ ---- %p",copyStr,copyStr);
    NSLog(@"%@ ---- %p",mCopyStr,mCopyStr);


//運(yùn)行結(jié)果:
2018-09-19 17:38:08.698067+0800 Demo[1696:261980] 111 ---- 0x2831745a0
2018-09-19 17:38:08.698234+0800 Demo[1696:261980] 111 ---- 0xa000000003131313
2018-09-19 17:38:08.698280+0800 Demo[1696:261980] 111 ---- 0x283174450
2018-09-19 17:38:08.698323+0800 Demo[1696:261980] 111,222 ---- 0x2831745a0
2018-09-19 17:38:08.698391+0800 Demo[1696:261980] 111 ---- 0xa000000003131313
2018-09-19 17:38:08.698432+0800 Demo[1696:261980] 111 ---- 0x283174450

對非集合可變對象進(jìn)行copy、mutableCopy時(shí),可以看到其內(nèi)存地址都發(fā)生了變化,所以這里的copy、mutableCopy都為深拷貝,對原有mStr操作,不會(huì)影響拷貝之后的值。

  • 集合可變對象(copy、mutableCopy)
    NSMutableArray *arrM = [NSMutableArray arrayWithObject:@"11"];
    NSMutableArray *copyArrM = [arrM copy];
    NSMutableArray *mCopyArrM = [arrM mutableCopy];
    NSLog(@"%@ ---- \n%p",arrM,arrM);
    NSLog(@"%@ ---- \n%p",mCopyArrM,mCopyArrM);
    NSLog(@"%@ ---- \n%p",copyArrM,copyArrM);
    [arrM addObject:@"22"];
    NSLog(@"%@ ---- \n%p",arrM,arrM);
    NSLog(@"%@ ---- \n%p",mCopyArrM,mCopyArrM);
    NSLog(@"%@ ---- \n%p",copyArrM,copyArrM);


//運(yùn)行結(jié)果:
2018-09-19 17:52:49.603180+0800 Demo[1708:264782] (
    11
) ---- 
0x282316d90
2018-09-19 17:52:49.603424+0800 Demo[1708:264782] (
    11
) ---- 
0x282317540
2018-09-19 17:52:49.603533+0800 Demo[1708:264782] (
    11
) ---- 
0x282f4c6a0
2018-09-19 17:52:49.603603+0800 Demo[1708:264782] (
    11,
    22
) ---- 
0x282316d90
2018-09-19 17:52:49.603660+0800 Demo[1708:264782] (
    11
) ---- 
0x282317540
2018-09-19 17:52:49.603716+0800 Demo[1708:264782] (
    11
) ---- 
0x282f4c6a0
  • 集合不可變對象(copy、mutableCopy)
    NSArray *arr = [NSArray arrayWithObject:@"11"];
    NSArray *copyArr = [arr copy];
    NSMutableArray *mCopyArr = [arr mutableCopy];
    NSLog(@"%@ ---- \n%p",arr,arr);
    NSLog(@"%@ ---- \n%p",copyArr,copyArr);
    NSLog(@"%@ ---- \n%p",mCopyArr,mCopyArr);

//運(yùn)行結(jié)果:
2018-09-19 17:57:24.646701+0800 Demo[1717:266299] (
    11
) ---- 
0x2808b81d0
2018-09-19 17:57:24.646878+0800 Demo[1717:266299] (
    11
) ---- 
0x2808b81d0
2018-09-19 17:57:24.647042+0800 Demo[1717:266299] (
    11
) ---- 
0x2804e1ef0

其實(shí)對集合不可變對象、集合可變對象進(jìn)行copy和mutableCopy結(jié)果可以參考非集合不可變對象、非集合可變對象的結(jié)果

最后對delegate為什么要用weak修飾簡單談下個(gè)人的看法

delegate在平常的使用中一般如下:


VC中擁有一個(gè)View,那么View的引用計(jì)數(shù)+1,而View中有delegate,那么delegate的引用計(jì)數(shù)+1。接著我們會(huì)在VC中有view.delegate = self,那么如果view用strong修飾,此時(shí)引用計(jì)數(shù)+1,此時(shí)view的引用計(jì)數(shù)為2。那么當(dāng)VC銷毀時(shí),view的引用計(jì)數(shù)-1,此時(shí)view的引用計(jì)數(shù)為1。那么view是無法銷毀的,然后view又引用著delegate,所以view和delegate一直會(huì)在內(nèi)存中的。那么如果用weak修飾delegate的,view的引用計(jì)數(shù)就為1,等到VC銷毀的時(shí)候,view計(jì)數(shù)-1,也回跟著銷毀,那么view引用的delegate也會(huì)銷毀。
以上是個(gè)人的一點(diǎn)愚見,如有錯(cuò)誤,歡迎大家指正。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容