iOS內存管理retain,assign,copy,strong,weak

iOS目前已經是ARC 時代。但對于要想了解ARC的內存管理機制,還是依舊需要對MRC時代的內存管理機制有深刻的理解才能掌握ARC。
話不多說,直接開干。

第一點

我們在創建一個對象的時候,不論是ARC 還是MRC 一般都是這樣創建的

NSMutableArray aArray = [[NSArray alloc] init];
NSMutableArray aArray = aArray.mutableCopy;

(一般情況下: 后面會討論例外情況)
alloc 對象分配空間后,引用計數為1
retain 對象的引用計數+1,不會對對象分配空間
copy copy 一個對象變成新的對象(新內存地址) 引用計數為1 原來對象計數不變(就是說,copy是將copy的對象復制一份,作為新的對象,然后分配空間,賦予新地址,再將其引入計數+1)
release 對象的引用計數-1 如果為該對象的引入計數減到 0 時,該對象釋立即放內存
autorelease 對象引用計數-1 如果為0不馬上釋放,最近一個個pool時釋放

NSLog(@"sMessage retainCount:%u",[sMessage retainCount]); //打印對象引入計數的個數

第二點(內存管理的原則)

內存管理的原則 就是最終的引用計數要平衡如果最后引用計數大于0 則會內存泄露

 __weak typeof(self) weakSelf = self 

    [MM_Factory addLeftButtonForVC:self imgName:@"left_mm_oa" hightligthImgName:nil title:nil clickedHandler:^{

        [weakSelf.navigationController popViewControllerAnimated:YES];

    }];

如果這里的weakSelf 還是self 則就會造成引入計數加1(block中如果不作為copy處理,會造成原有對象引入技術加1)所以會造成內存泄露。
如果引用 計數等于 0 還對該對象進行操作,則會出現內存訪問失敗,crash 所以盡量設置為nil
這兩個問題都很嚴重,所以請一定注意內存釋放和不用過后設置為nil


第三點 (成員變量與屬性)

實際情況并非上面那么簡單,你可能需要在一個函數里調用另一個函數分配的變量這時候有兩個選擇: 類成員變量使用屬性

@interface TestMem: NSObject {
    TestObject *m_testObject ;   //**成員變量**
    TestObject *testObject;      //**成員變量**
}

成員變量與上面的內存管理是一致的,只是在不同的函數里要保持引用計數加減的平衡所以要你要每次分配的時候檢查是否上次已經分配了。是否還能調用什么時候用屬性?

  1. 把成員做為public.(公開對象)
  2. outlet 一般聲明為屬性( 這個內存于系統控制,但我們還是應該做一樣操作,后面會講)
  3. 如果很多函數都需要改變這個對象 ,或這個函數會觸發很多次,建議使用屬性

我們看看屬性函數展開后是什么樣子:

**
**// assign
**
-(void)setTestObject :(id)newValue{
   testObject= newValue;
}

**// retain
**
-(void)setTestObject :(id)newValue{
    if (testObject!= newValue) {
        [testObject release];
        testObject= [newValue retain];
    }
}

**// copy
**
-(void)setTestObject :(id)newValue{
    if (testObject != newValue) {
        [testObject release];
        testObject = [newValue copy];
    }
}

asssign 相于于指針賦值,不對引用計數進行操作,注意原對象不用了,一定要把這個設置為nil
retain 相當于對原對象的引用計數加1
copy 不對原對象的引用計數改變,生成一個新對象引用計數為1

注意: self.testObject 左值調用的是set TestObject 方法. 右值為get方法,get 方法比較簡單不用說了而 真接testObject 使用的是成員變量self.testObject = [[testObject alloc] init];
// 錯 reatin 兩次
(就是說,對于self..testObject 已經是創建對象并將引入技術+1,如果后面繼續用 [testObject alloc] init]會造成引入計數繼續+1,所以是2次 )testObject = [NSArray objectbyindex:0];
//錯 不安全,沒有retain 后面release會出錯
(這里沒有用 self. 說明 不會調用 set方法,所以引入計數仍然為 0 ,如果后面 進行release操作, 則會造成 內存訪問失敗)如果testObject已有值也會memory leak 內存泄露

自動管理對象iOS 提供了很多static(+) 創建對象的類方法,這些方面是靜態的,可以直接用類名調用如:

NSString *testString = [NSString stringWithFormat:@"test" ];

testString 是自動管理的對象,你不用relese 他,他有一個很大的 retain count, release后數字不變。
例外有一些通過alloc 生成的對象相同是自動管理的如:

NSString *testString = [[NSString alloc] initWithString:@"test1"];

retain count 同樣是很大的數,沒辦法release

但為了代碼對應,還是應該加上[ testString release]; //MRC 中需要不然xcode的Analyze 會認識內存leak, 但Instruments leak 工具檢測是沒有的

第四點(strongweak

iOS 5 中對屬性的設置新增了strong 和weak關鍵字來修飾屬性(iOS 5 之前不支持ARC)

strong 用來修飾強引用的屬性;
@property (strong) SomeClass * aObject;

對應原來的
@property (retain) SomeClass * aObject;
和 @property (copy) SomeClass * aObject;

weak 用來修飾弱引用的屬性
@property (weak) SomeClass * aObject;
對應原來的@property (assign) SomeClass * aObject;

第五點(iOS內存nil與release的區別)

nil和release的作用:nil就是把一個對象的指針置為空,只是切斷了指針與內存中對象的聯系;
而release才是真正通知內存釋放這個對象,但是在iOS中其實也不會立馬釋放內存,而是將內存計數器剪去1,直到計數器變為0,才會釋放掉內存,
所以release的目的是為了釋放內存,而self.object = nil,是清空指針。

所以nil并沒有釋放內存,只有release才回真正釋放內存。

二者使用的先后順序:如果沒有release就直接nil,那么雖然不會出錯,卻等于自己制造內存泄漏了,因為nil之后release就已經不起作用了。相反,如果在使用接口對象時只僅僅release沒有設置self.myOutlet = nil,那么程序可能也不會報錯,但卻會十分不穩定、不健壯,很容易發生崩潰現象。因為一個接口對象在release之后,給它所分配等內存就已經被釋放了,如果釋放之后系統再用到這個對象,那么程序就會crash。如果釋放之后把它的指針置為空,則即便后面的程序用到該對象,也不會崩潰。

strong類似于retain
weak類似于assign

第六點(copy 和 retain 的區別)

copy: 建立一個索引計數為1的對象,然后釋放舊對象
retain: 釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1那上面的是什么該死的意思呢?
Copy其實是建立了一個相同的對象,相當于是備份,而retain不是:比如一個NSString對象,地址為0×1111,內容為@”STR”Copy到另外一個NSString之后,地址為0×2222,內容相同,新的對象retain為1,舊有對象沒有變化retain到另外一個NSString之后,地址相同(建立一個指針,指針拷貝),內容當然相同,這個對象的retain值+1也就是說,retain是指針拷貝,copy是內容拷貝。哇,比想象的簡單多了…

第七點(對autorelease的誤解)autorelease其實是“延后釋放”

A Cocoa的內存管理分為 索引計數法(Reference Counting/ Retain Count)和 垃圾收集法(Garbage Collection)。
而iPhone上目前只支持前者,所以autorelease就成為很多人的“捷徑”。但是!autorelease其實并不是“自動釋放”,不像垃圾收集法,對對象之間的關系偵測后發現垃圾-刪除。
但是autorelease其實是“延后釋放”,在一個運行周期后被標記為autorelease會被釋放掉。切記小心使用autorelease,理解autorelease,防止在你還需要該對象的時候已經被系統釋放掉了。

第八點(其它)

NSArray對象會retain(retain值加一+1)任何數組中的對象。當NSArray被卸載(dealloc)的時候,所有數組中的對象會被執行一次釋放(retain值減一)。
不僅僅是NSArray,任何收集類(Collection Classes)都執行類似操作。例如NSDictionary,甚至UINavigationController。Alloc/init建立的對象,索引計數為1。無需將其再次retain。
為什么不能直接調用dealloc而是release dealloc不等于C中的free,dealloc并不將內存釋放,也不會將索引計數(Reference counting)降低。
于是直接調用dealloc反而無法釋放內存。
只是當當前情景下,如果創建的所有對象、屬性、成員變量等引入技術均為0 時,不會造成內存泄露,就會調用 dealloc 方法。
所以可以用以下方法 檢測 iOS 頁面是否出現內存泄露的請款
在Objective-C中,索引計數是起決定性作用的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容