__Strong ?__weak ?__autorelease ?__unsafe_unretained _copy 關鍵字的本質和用法

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.1 什么是自動引用計數 概念:在 LLVM 編譯器中設置 ARC(Automaitc Reference Co...
    __silhouette閱讀 5,241評論 1 17
  • 前言 從我開始學習iOS的時候,身邊的朋友、網上的博客都告訴我iOS的內存管理是依靠引用計數的,然后說引用計數大于...
    蓋世英雄_ix4n04閱讀 574評論 0 1
  • 自動引用計數 自動引用計數:指內存管理中對引用采取自動計數的技術。 內存管理/引用計數 持有對象引起引用計數加...
    南京小伙閱讀 1,329評論 2 3
  • 天空中,風雨交加。 我來到我表弟家。我的表弟頭發垂在頭上。大大的眼睛,小小的鼻子,小小的嘴,皮膚嫩嫩的,耳朵仿佛能...
    張墨涵閱讀 158評論 4 2
  • 1.為什么我有玉米 2.為什么蟑螂吃玉米 3.為什么我的玉米被蟑螂吃了 1.因為我想吃,那天就買了,如果我沒買,我...
    Lexynna閱讀 2,716評論 0 0