iOS內(nèi)存管理retain渴杆,assign,copy宪塔,strong磁奖,weak

iOS目前已經(jīng)是ARC 時(shí)代。但對(duì)于要想了解ARC的內(nèi)存管理機(jī)制某筐,還是依舊需要對(duì)MRC時(shí)代的內(nèi)存管理機(jī)制有深刻的理解才能掌握ARC比搭。
話(huà)不多說(shuō),直接開(kāi)干南誊。

第一點(diǎn)

我們?cè)趧?chuàng)建一個(gè)對(duì)象的時(shí)候身诺,不論是ARC 還是MRC 一般都是這樣創(chuàng)建的

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

(一般情況下: 后面會(huì)討論例外情況)
alloc 對(duì)象分配空間后,引用計(jì)數(shù)為1
retain 對(duì)象的引用計(jì)數(shù)+1抄囚,不會(huì)對(duì)對(duì)象分配空間
copy copy 一個(gè)對(duì)象變成新的對(duì)象(新內(nèi)存地址) 引用計(jì)數(shù)為1 原來(lái)對(duì)象計(jì)數(shù)不變(就是說(shuō)霉赡,copy是將copy的對(duì)象復(fù)制一份,作為新的對(duì)象幔托,然后分配空間穴亏,賦予新地址,再將其引入計(jì)數(shù)+1)
release 對(duì)象的引用計(jì)數(shù)-1 如果為該對(duì)象的引入計(jì)數(shù)減到 0 時(shí)重挑,該對(duì)象釋立即放內(nèi)存
autorelease 對(duì)象引用計(jì)數(shù)-1 如果為0不馬上釋放嗓化,最近一個(gè)個(gè)pool時(shí)釋放

NSLog(@"sMessage retainCount:%u",[sMessage retainCount]); //打印對(duì)象引入計(jì)數(shù)的個(gè)數(shù)

第二點(diǎn)(內(nèi)存管理的原則)

內(nèi)存管理的原則 就是最終的引用計(jì)數(shù)要平衡如果最后引用計(jì)數(shù)大于0 則會(huì)內(nèi)存泄露

 __weak typeof(self) weakSelf = self 

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

        [weakSelf.navigationController popViewControllerAnimated:YES];

    }];

如果這里的weakSelf 還是self 則就會(huì)造成引入計(jì)數(shù)加1(block中如果不作為copy處理,會(huì)造成原有對(duì)象引入技術(shù)加1)所以會(huì)造成內(nèi)存泄露谬哀。
如果引用 計(jì)數(shù)等于 0 還對(duì)該對(duì)象進(jìn)行操作刺覆,則會(huì)出現(xiàn)內(nèi)存訪問(wèn)失敗,crash 所以盡量設(shè)置為nil
這兩個(gè)問(wèn)題都很?chē)?yán)重玻粪,所以請(qǐng)一定注意內(nèi)存釋放和不用過(guò)后設(shè)置為nil


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

實(shí)際情況并非上面那么簡(jiǎn)單隅津,你可能需要在一個(gè)函數(shù)里調(diào)用另一個(gè)函數(shù)分配的變量這時(shí)候有兩個(gè)選擇: 類(lèi)成員變量使用屬性

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

成員變量與上面的內(nèi)存管理是一致的诬垂,只是在不同的函數(shù)里要保持引用計(jì)數(shù)加減的平衡所以要你要每次分配的時(shí)候檢查是否上次已經(jīng)分配了。是否還能調(diào)用什么時(shí)候用屬性?

  1. 把成員做為public.(公開(kāi)對(duì)象)
  2. outlet 一般聲明為屬性( 這個(gè)內(nèi)存于系統(tǒng)控制伦仍,但我們還是應(yīng)該做一樣操作结窘,后面會(huì)講)
  3. 如果很多函數(shù)都需要改變這個(gè)對(duì)象 ,或這個(gè)函數(shù)會(huì)觸發(fā)很多次充蓝,建議使用屬性

我們看看屬性函數(shù)展開(kāi)后是什么樣子:

**
**// 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 相于于指針賦值隧枫,不對(duì)引用計(jì)數(shù)進(jìn)行操作,注意原對(duì)象不用了谓苟,一定要把這個(gè)設(shè)置為nil
retain 相當(dāng)于對(duì)原對(duì)象的引用計(jì)數(shù)加1
copy 不對(duì)原對(duì)象的引用計(jì)數(shù)改變官脓,生成一個(gè)新對(duì)象引用計(jì)數(shù)為1

注意: self.testObject 左值調(diào)用的是set TestObject 方法. 右值為get方法,get 方法比較簡(jiǎn)單不用說(shuō)了而 真接testObject 使用的是成員變量self.testObject = [[testObject alloc] init];
// 錯(cuò) reatin 兩次
(就是說(shuō)涝焙,對(duì)于self..testObject 已經(jīng)是創(chuàng)建對(duì)象并將引入技術(shù)+1卑笨,如果后面繼續(xù)用 [testObject alloc] init]會(huì)造成引入計(jì)數(shù)繼續(xù)+1,所以是2次 )testObject = [NSArray objectbyindex:0];
//錯(cuò) 不安全仑撞,沒(méi)有retain 后面release會(huì)出錯(cuò)
(這里沒(méi)有用 self. 說(shuō)明 不會(huì)調(diào)用 set方法赤兴,所以引入計(jì)數(shù)仍然為 0 ,如果后面 進(jìn)行release操作隧哮, 則會(huì)造成 內(nèi)存訪問(wèn)失斖傲肌)如果testObject已有值也會(huì)memory leak 內(nèi)存泄露

自動(dòng)管理對(duì)象iOS 提供了很多static(+) 創(chuàng)建對(duì)象的類(lèi)方法,這些方面是靜態(tài)的沮翔,可以直接用類(lèi)名調(diào)用如:

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

testString 是自動(dòng)管理的對(duì)象陨帆,你不用relese 他,他有一個(gè)很大的 retain count, release后數(shù)字不變采蚀。
例外有一些通過(guò)alloc 生成的對(duì)象相同是自動(dòng)管理的如:

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

retain count 同樣是很大的數(shù)疲牵,沒(méi)辦法release

但為了代碼對(duì)應(yīng),還是應(yīng)該加上[ testString release]; //MRC 中需要不然xcode的Analyze 會(huì)認(rèn)識(shí)內(nèi)存leak, 但I(xiàn)nstruments leak 工具檢測(cè)是沒(méi)有的

第四點(diǎn)(strongweak

iOS 5 中對(duì)屬性的設(shè)置新增了strong 和weak關(guān)鍵字來(lái)修飾屬性(iOS 5 之前不支持ARC)

strong 用來(lái)修飾強(qiáng)引用的屬性搏存;
@property (strong) SomeClass * aObject;

對(duì)應(yīng)原來(lái)的
@property (retain) SomeClass * aObject;
和 @property (copy) SomeClass * aObject;

weak 用來(lái)修飾弱引用的屬性
@property (weak) SomeClass * aObject;
對(duì)應(yīng)原來(lái)的@property (assign) SomeClass * aObject;

第五點(diǎn)(iOS內(nèi)存nil與release的區(qū)別)

nil和release的作用:nil就是把一個(gè)對(duì)象的指針置為空瑰步,只是切斷了指針與內(nèi)存中對(duì)象的聯(lián)系;
而release才是真正通知內(nèi)存釋放這個(gè)對(duì)象璧眠,但是在iOS中其實(shí)也不會(huì)立馬釋放內(nèi)存缩焦,而是將內(nèi)存計(jì)數(shù)器剪去1,直到計(jì)數(shù)器變?yōu)?责静,才會(huì)釋放掉內(nèi)存袁滥,
所以release的目的是為了釋放內(nèi)存,而self.object = nil灾螃,是清空指針题翻。

所以nil并沒(méi)有釋放內(nèi)存,只有release才回真正釋放內(nèi)存。

二者使用的先后順序:如果沒(méi)有release就直接nil嵌赠,那么雖然不會(huì)出錯(cuò)塑荒,卻等于自己制造內(nèi)存泄漏了,因?yàn)閚il之后release就已經(jīng)不起作用了姜挺。相反齿税,如果在使用接口對(duì)象時(shí)只僅僅release沒(méi)有設(shè)置self.myOutlet = nil,那么程序可能也不會(huì)報(bào)錯(cuò)炊豪,但卻會(huì)十分不穩(wěn)定凌箕、不健壯,很容易發(fā)生崩潰現(xiàn)象词渤。因?yàn)橐粋€(gè)接口對(duì)象在release之后牵舱,給它所分配等內(nèi)存就已經(jīng)被釋放了,如果釋放之后系統(tǒng)再用到這個(gè)對(duì)象缺虐,那么程序就會(huì)crash芜壁。如果釋放之后把它的指針置為空,則即便后面的程序用到該對(duì)象高氮,也不會(huì)崩潰沿盅。

strong類(lèi)似于retain
weak類(lèi)似于assign

第六點(diǎn)(copy 和 retain 的區(qū)別)

copy: 建立一個(gè)索引計(jì)數(shù)為1的對(duì)象,然后釋放舊對(duì)象
retain: 釋放舊的對(duì)象纫溃,將舊對(duì)象的值賦予輸入對(duì)象,再提高輸入對(duì)象的索引計(jì)數(shù)為1那上面的是什么該死的意思呢韧掩?
Copy其實(shí)是建立了一個(gè)相同的對(duì)象紊浩,相當(dāng)于是備份,而retain不是:比如一個(gè)NSString對(duì)象疗锐,地址為0×1111坊谁,內(nèi)容為@”STR”Copy到另外一個(gè)NSString之后,地址為0×2222滑臊,內(nèi)容相同口芍,新的對(duì)象retain為1,舊有對(duì)象沒(méi)有變化retain到另外一個(gè)NSString之后雇卷,地址相同(建立一個(gè)指針鬓椭,指針拷貝),內(nèi)容當(dāng)然相同关划,這個(gè)對(duì)象的retain值+1也就是說(shuō)小染,retain是指針拷貝,copy是內(nèi)容拷貝贮折。哇裤翩,比想象的簡(jiǎn)單多了…

第七點(diǎn)(對(duì)autorelease的誤解)autorelease其實(shí)是“延后釋放”

A Cocoa的內(nèi)存管理分為 索引計(jì)數(shù)法(Reference Counting/ Retain Count)和 垃圾收集法(Garbage Collection)。
而iPhone上目前只支持前者调榄,所以autorelease就成為很多人的“捷徑”踊赠。但是呵扛!autorelease其實(shí)并不是“自動(dòng)釋放”,不像垃圾收集法筐带,對(duì)對(duì)象之間的關(guān)系偵測(cè)后發(fā)現(xiàn)垃圾-刪除今穿。
但是autorelease其實(shí)是“延后釋放”,在一個(gè)運(yùn)行周期后被標(biāo)記為autorelease會(huì)被釋放掉烫堤。切記小心使用autorelease荣赶,理解autorelease,防止在你還需要該對(duì)象的時(shí)候已經(jīng)被系統(tǒng)釋放掉了鸽斟。

第八點(diǎn)(其它)

NSArray對(duì)象會(huì)retain(retain值加一+1)任何數(shù)組中的對(duì)象拔创。當(dāng)NSArray被卸載(dealloc)的時(shí)候,所有數(shù)組中的對(duì)象會(huì)被執(zhí)行一次釋放(retain值減一)富蓄。
不僅僅是NSArray剩燥,任何收集類(lèi)(Collection Classes)都執(zhí)行類(lèi)似操作。例如NSDictionary立倍,甚至UINavigationController灭红。Alloc/init建立的對(duì)象,索引計(jì)數(shù)為1口注。無(wú)需將其再次retain变擒。
為什么不能直接調(diào)用dealloc而是release dealloc不等于C中的free,dealloc并不將內(nèi)存釋放寝志,也不會(huì)將索引計(jì)數(shù)(Reference counting)降低娇斑。
于是直接調(diào)用dealloc反而無(wú)法釋放內(nèi)存。
只是當(dāng)當(dāng)前情景下材部,如果創(chuàng)建的所有對(duì)象毫缆、屬性、成員變量等引入技術(shù)均為0 時(shí)乐导,不會(huì)造成內(nèi)存泄露苦丁,就會(huì)調(diào)用 dealloc 方法。
所以可以用以下方法 檢測(cè) iOS 頁(yè)面是否出現(xiàn)內(nèi)存泄露的請(qǐng)款
在Objective-C中物臂,索引計(jì)數(shù)是起決定性作用的旺拉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市棵磷,隨后出現(xiàn)的幾起案子账阻,更是在濱河造成了極大的恐慌,老刑警劉巖泽本,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淘太,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蒲牧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)撇贺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人冰抢,你說(shuō)我怎么就攤上這事松嘶。” “怎么了挎扰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵翠订,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我遵倦,道長(zhǎng)尽超,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任梧躺,我火速辦了婚禮似谁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掠哥。我一直安慰自己巩踏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布续搀。 她就那樣靜靜地躺著塞琼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪禁舷。 梳的紋絲不亂的頭發(fā)上屈梁,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音榛了,去河邊找鬼。 笑死煞抬,一個(gè)胖子當(dāng)著我的面吹牛霜大,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播革答,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼战坤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了残拐?” 一聲冷哼從身側(cè)響起途茫,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎溪食,沒(méi)想到半個(gè)月后囊卜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年栅组,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雀瓢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡玉掸,死狀恐怖刃麸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情司浪,我是刑警寧澤泊业,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站啊易,受9級(jí)特大地震影響吁伺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜认罩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一箱蝠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧垦垂,春花似錦宦搬、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至页慷,卻和暖如春憔足,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酒繁。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工滓彰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人州袒。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓揭绑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親郎哭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子他匪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • IOS的對(duì)象都繼承于NSObject, 該對(duì)象有一個(gè)方法:retainCount 井辆,內(nèi)存引用計(jì)數(shù)关筒。 引用計(jì)數(shù)在很多...
    請(qǐng)叫我周小帥閱讀 262評(píng)論 0 2
  • 內(nèi)存管理 簡(jiǎn)述OC中內(nèi)存管理機(jī)制。與retain配對(duì)使用的方法是dealloc還是release杯缺,為什么蒸播?需要與a...
    丶逐漸閱讀 1,950評(píng)論 1 16
  • 1. 內(nèi)總管理原則(引用計(jì)數(shù)) IOS的對(duì)象都繼承于NSObject, 該對(duì)象有一個(gè)方法:retainCount...
    lilinjianshu閱讀 2,151評(píng)論 0 2
  • iOS內(nèi)存管理 概述 什么是內(nèi)存管理 應(yīng)用程序內(nèi)存管理是在程序運(yùn)行時(shí)分配內(nèi)存(比如創(chuàng)建一個(gè)對(duì)象,會(huì)增加內(nèi)存占用)與...
    蚊香醬閱讀 5,704評(píng)論 8 119
  • 29.理解引用計(jì)數(shù) Objective-C語(yǔ)言使用引用計(jì)數(shù)來(lái)管理內(nèi)存,也就是說(shuō)萍肆,每個(gè)對(duì)象都有個(gè)可以遞增或遞減的計(jì)數(shù)...
    Code_Ninja閱讀 1,475評(píng)論 1 3