1.__Strong? ARC 無效時,引用計數器加1,當超出作用域,引用為nil,由于未執行release 方法,對象還存在堆中,而此時引用銷毀了,對象沒有銷毀,出現內存泄漏
ARC 有效時,引用計數器加1,當超出作用域,當系統判斷引用為nil時,系統自動銷毀對象。
ARC 情況下
2.__Weak ?ARC 不持有對象,自動加入自動釋放池autorelaesepool;
(1.)不持有對象,
例如 id __weak obj = [[ NSObject alloc ]init];系統警告,發現是以__weak 修飾的引用obj 系統會在創建好對象后,自動release掉。
(2.)自動加入自動釋放池
例如 id __strong ?obj =? [[ NSObject alloc ]init];
id __weak obj1=obj;{
偽代碼如下:id__weak obj1 = obj,
id _autoreleasing tmp = obj1; ? ?(加入自動釋放池)
}
obj超出作用域,引用為nil,同時obj1引用為nil,(對象是否銷毀要看系統什么時候銷毀自動釋放池,此時只是兩個引用為nil)自動釋放池此時持有對象,自動釋放池銷毀時銷毀對象(系統在合適的時機銷毀自動釋放池)這個合適的時機就是當前的RunLoop循環結束。
3.__autorelease 將對象放入自動釋放池,系統在合適的時機銷毀自動釋放池,同時銷毀池內的對象。
4.__unsafe_unretained 不安全的所有權修飾符,如果用__unsafe_unretained 修飾的引用指向對象系統報錯,同__weak,? 例如 id?__unsafe_unretained obj = [[ NSObject alloc ]init];系統? 警告,
例如 id __strong ?obj =? [[ NSObject alloc ]init];
id __unsafe_unretained obj1=obj;
obj 賦值給obj1,既不持有對象的強引用,也不持有對象的弱引用,當obj 超出作用域時,引用對象銷毀,obj為nil,obj1為野指針。
ARC
1.__strong 的具體實現
id obj(默認strong)=? [[ NSObject alloc ]init];
id obj = objc_msgSend(NSObject,@selector(alloc));
objc_msgSend(obj,@selector(init));
當超出obj 的作用域時自動銷毀
2.__weak 的具體實現
id obj(默認strong)=? [[ NSObject alloc ]init];
賦值為nil
id __weak obj1 = obj
obj1 = 0;
objc_storeWeak(&obj1,obj)
objc_storeWeak(&obj1,o)
(把第二參數的地址作為鍵值,將對參數的附有__weak 修飾符的變量注冊到weak 表中,如果第二參數為0,記obj超出作用域或者obj為nil 則把變量地址從weak 表中刪除,將obj1賦值為nil)
注冊到自動釋放池
objc_initWeak (&obj1,obj);
id temp = objc_loadWeakRetained(&obj1) (引用計數加1)
objc_autorelease(temp);
系統發現用__weak 修飾時通過 objc_loadWeakRetained 函數取出__weak 修飾符變量所引用的對象retain,然后放入自動釋放池,objc引用超出作用域,指針銷毀,obj1銷毀,對象等自動釋放池釋放時銷毀。
5copy?
copy 分為三種情況
1.當修飾,NSMutableString NSMutableArry 等可變的字符串或者數組時,必須用copy,因為strong 是單純增加對象的引用計數,改變的同時會同時改變源對象,而copy 是做的深拷貝,改變對象的同時,對源對象沒有影響,所以必須用copy。
2.當修飾不可變字符串或者數組,字典時分為兩種情況
1.當傳入的對象也為不可變對象時,用copy和strong 沒有區別,例如
1.
NSString *textStr = @“TextString”;
self.StrStrong = textStr;
self.strCopy ? =textStr;
當textStr 的值改變時,self.StrStrong或者self.StrStrong 的值并不會因為textStr的值改變而發生改變,因為不可變字符串在代碼區,例如當textStr = @“TextString” 時,textStr 指向的是TextString 的首地址,而當textStr = @“TextString1”,textStr 指向的是TextString1 的首地址
記當textStr = @“TextString”;self.StrStrong = textStr;self.StrStrong = strCopy;時,他們三個的地址都是指向“TextString”的首地址,當self.StrStrong = @"TextChange" 時,textStr和self.strCopy還是指向TextString,所以他們三個當中任意一個的值改變都不會影響到對方,所以用Strong和copy 沒有任何區別.
2.
NSMutableString *textStr = ?[NSMutableString stringWithString:@"textStr"];
self.StrStrong = textStr;(指向的是對象textStr,強引用,引用計數器加1)
self.strCopy= textStr;(對對象textStr 的一次深拷貝)
當textStr 的值改變時,self.StrStrong 的值會發生改變因為self.StrStrong和textStr指向的是同一個對象,而self.strCopy對textStr做的是深拷貝,所以值不會發生改變。所以在進行賦值操作時如果接收的對象是可變對象,也必須用copy。
注意:因為在進行賦值操作時,我們并不能確定傳遞的是可變字符串、字典、數組,還是不可變字符串、字典、數組。所以我們應該統一用copy 這樣就可以避免出現對象改變的情況,bug出現的幾率會大大降低,所以建議不管是可變不可變時都統一用copy