內(nèi)存管理retain碗降,assign,copy塘秦,strong讼渊,weak

IOS的對(duì)象都繼承于NSObject, 該對(duì)象有一個(gè)方法:retainCount ,內(nèi)存引用計(jì)數(shù)尊剔。 引用計(jì)數(shù)在很多技術(shù)都用到: window下的COM組件爪幻,多線程的信號(hào)量,讀寫(xiě)鎖须误,思想都一樣挨稿。

(一般情況下: 后面會(huì)討論例外情況)

alloc 對(duì)象分配后引用計(jì)數(shù)為1

retain 對(duì)象的引用計(jì)數(shù)+1

copy copy 一個(gè)對(duì)象變成新的對(duì)象(新內(nèi)存地址) 引用計(jì)數(shù)為1 原來(lái)對(duì)象計(jì)數(shù)不變

release 對(duì)象引用計(jì)數(shù)-1 如果為0釋放內(nèi)存

autorelease 對(duì)象引用計(jì)數(shù)-1 如果為0不馬上釋放,最近一個(gè)個(gè)pool時(shí)釋放

NSLog(@"sMessage retainCount:%u",[sMessage retainCount]);

內(nèi)存管理的原則就是最終的引用計(jì)數(shù)要平衡,

如果最后引用計(jì)數(shù)大于0 則會(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

成員變量與屬性

實(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.

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)用的是setTestObject 方法. 右值為get方法钱慢,get 方法比較簡(jiǎn)單不用說(shuō)了

而 真接testObject 使用的是成員變量

self.testObject = [[testObject alloc] init]; // 錯(cuò) reatin 兩次

testObject = [NSArray objectbyindex:0]; //錯(cuò) 不安全,沒(méi)有retain 后面release會(huì)出錯(cuò)

如果testObject已有值也會(huì)mem leak

自動(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ù)字不變览绿。

5.?例外

有一些通過(guò)alloc 生成的對(duì)象相同是自動(dòng)管理的如:

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

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

但為了代碼對(duì)應(yīng)穗慕,還是應(yīng)該加上[ testString release];

不然xcode的Analyze 會(huì)認(rèn)識(shí)內(nèi)存leak, 但I(xiàn)nstruments leak 工具檢測(cè)是沒(mé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ù)字不變。

5.?例外

有一些通過(guò)alloc 生成的對(duì)象相同是自動(dòng)管理的如:

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

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

但為了代碼對(duì)應(yīng)瓢对,還是應(yīng)該加上[ testString release];

不然xcode的Analyze 會(huì)認(rèn)識(shí)內(nèi)存leak, 但I(xiàn)nstruments leak 工具檢測(cè)是沒(méi)有的

IOS內(nèi)存管理詳解

copy?和 retain 的區(qū)別

copy: 建立一個(gè)索引計(jì)數(shù)為1的對(duì)象,然后釋放舊對(duì)象

retain:釋放舊的對(duì)象胰苏,將舊對(duì)象的值賦予輸入對(duì)象硕蛹,再提高輸入對(duì)象的索引計(jì)數(shù)為1

那上面的是什么該死的意思呢?

Copy其實(shí)是建立了一個(gè)相同的對(duì)象硕并,而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)單多了…

誤釋放對(duì)象

問(wèn)題一:

1.value = [array objectAtIndex:n]; //得到一個(gè)數(shù)組中的對(duì)象

2.[arry removeObjectAtIndex:n]; //卸載那個(gè)對(duì)象

?????value = [array objectAtIndex:n]; //得到一個(gè)數(shù)組中的對(duì)象

[arry removeObjectAtIndex:n]; //卸載那個(gè)對(duì)象

因?yàn)関alue得到了那個(gè)對(duì)象,但是由于另外一個(gè)擁有者release了該對(duì)象运准,所以其實(shí)value現(xiàn)在成了搖擺指針(無(wú)效數(shù)據(jù))

問(wèn)題二:

1.myArray = [NSArray array];

2....

3.[myArray release];

?????myArray = [NSArray array];

...

[myArray release];

NSArray返回的是一個(gè)自動(dòng)釋放對(duì)象幌氮,不僅myArray不應(yīng)該在一段時(shí)間后release,而應(yīng)該在適當(dāng)?shù)臅r(shí)候先retain胁澳,以防止該array被系統(tǒng)誤釋放该互。

問(wèn)題三:

1.rocket = [rocketLauncher aRocket];

2.[rocketLauncher release];

?????rocket = [rocketLauncher aRocket];

[rocketLauncher release];

和array這種數(shù)據(jù)收集類(lèi)對(duì)象一樣,如果我們得到了一個(gè)類(lèi)的子對(duì)象而不retain它韭畸,那么在原父類(lèi)被釋放的時(shí)候宇智,這個(gè)rocket其實(shí)也會(huì)失去其意義。

Cocoa不同內(nèi)存管理環(huán)境下的autorelease

H 混合內(nèi)存管理環(huán)境:垃圾收集法(Garbage Collection)+索引計(jì)數(shù)法(Reference Counting)

雖然大多數(shù)情況下混合環(huán)境是不被推薦的胰丁,但是如果在這個(gè)情況下随橘,autorelease需要注意以下事項(xiàng):

垃圾收集混合環(huán)境下:應(yīng)該使用drain方法,因?yàn)閞elease在GC模式下沒(méi)有意義

索引計(jì)數(shù)環(huán)境下:drain和release對(duì)于autoreleasepool(自動(dòng)釋放池)的效果相同

對(duì)autorelease的誤解

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)釋放掉了。

Interface Builder參與的內(nèi)存管理問(wèn)題

要點(diǎn):

如果一個(gè)變量在類(lèi)中被定義為了 IBOutlet 那么你無(wú)需對(duì)其進(jìn)行實(shí)例化汇恤,xib載入器會(huì)對(duì)其初始化庞钢。

如果一個(gè)變量在類(lèi)中被定義為了 IBOutlet 那么你必須負(fù)責(zé)將其釋放。xib載入器不會(huì)幫忙的… …

*切不要初始化兩回因谎,內(nèi)存會(huì)溢出基括,而且對(duì)象鎖定也會(huì)出錯(cuò)。

關(guān)于索引計(jì)數(shù)(Reference Counting)的問(wèn)題

1.*retain值 = 索引計(jì)數(shù)//(Reference Counting)

???*retain值 = 索引計(jì)數(shù)//(Reference Counting)

NSArray對(duì)象會(huì)retain(retain值加一)任何數(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。

[NSArray array]和[NSDate date]等“方法”建立一個(gè)索引計(jì)數(shù)為1的對(duì)象遏暴,但是也是一個(gè)自動(dòng)釋放對(duì)象侄刽。所以是本地臨時(shí)對(duì)象,那么無(wú)所謂了朋凉。如果是打算在全Class中使用的變量(iVar)州丹,則必須retain它。

缺省的類(lèi)方法返回值都被執(zhí)行了“自動(dòng)釋放”方法侥啤。(*如上中的NSArray)

在類(lèi)中的卸載方法“dealloc”中当叭,release所有未被平衡的NS對(duì)象。(*所有未被autorelease盖灸,而retain值為1的)

NSString的內(nèi)存管理

如下實(shí)例:

1.aString = @"I am a string that 2 years old, man!";

aString = @"I am a string that 2 years old, man!";

這種情況下,字符串儲(chǔ)存和管理由系統(tǒng)做磺芭,我們不用操心赁炎。

1.aString = [NSString stringWithFormat:@"I am a string that %d years old, man!",2];

aString = [NSString stringWithFormat:@"I am a string that %d years old, man!",2];

第二種情況下,我們需要去retain和release這個(gè)字符串钾腺,系統(tǒng)不管徙垫。

Objective-C內(nèi)存管理

1,你初始化(alloc/init)的對(duì)象放棒,你需要釋放(release)它姻报。例如:

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

NSMutableArray aArray = [[NSArray alloc] init];

后,需要

1.[aArray release];

[aArray release];

2间螟,你retain或copy的吴旋,你需要釋放它。例如:

1.[aArray retain]

[aArray retain]

后厢破,需要

1.[aArray release];

[aArray release];

3荣瑟,被傳遞(assign)的對(duì)象,你需要斟酌的retain和release摩泪。例如:

1.obj2 = [[obj1 someMethod] autorelease];

obj2 = [[obj1 someMethod] autorelease];

對(duì)象2接收對(duì)象1的一個(gè)自動(dòng)釋放的值笆焰,或傳遞一個(gè)基本數(shù)據(jù)類(lèi)型(NSInteger,NSString)時(shí): 你或希望將對(duì)象2進(jìn)行retain见坑,以防止它在被使用之前就被自動(dòng)釋放掉嚷掠。但是在retain后捏检,一定要在適當(dāng)?shù)臅r(shí)候進(jìn)行釋放。

為什么不能直接調(diào)用dealloc而是release

dealloc不等于C中的free不皆,dealloc并不將內(nèi)存釋放贯城,也不會(huì)將索引計(jì)數(shù)(Reference counting)降低。于是直接調(diào)用dealloc反而無(wú)法釋放內(nèi)存粟焊。

在Objective-C中冤狡,索引計(jì)數(shù)是起決定性作用的。

strong 和weak

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;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市香追,隨后出現(xiàn)的幾起案子合瓢,更是在濱河造成了極大的恐慌,老刑警劉巖透典,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晴楔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡峭咒,警方通過(guò)查閱死者的電腦和手機(jī)税弃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凑队,“玉大人则果,你說(shuō)我怎么就攤上這事′霭保” “怎么了西壮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)叫惊。 經(jīng)常有香客問(wèn)我款青,道長(zhǎng),這世上最難降的妖魔是什么霍狰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任抡草,我火速辦了婚禮,結(jié)果婚禮上蚓耽,老公的妹妹穿的比我還像新娘渠牲。我一直安慰自己,他們只是感情好步悠,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布签杈。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪答姥。 梳的紋絲不亂的頭發(fā)上铣除,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音鹦付,去河邊找鬼尚粘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敲长,可吹牛的內(nèi)容都是我干的郎嫁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼祈噪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼泽铛!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起辑鲤,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤盔腔,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后月褥,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體弛随,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年宁赤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舀透。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡决左,死狀恐怖盐杂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哆窿,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布厉斟,位于F島的核電站挚躯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏擦秽。R本人自食惡果不足惜码荔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望感挥。 院中可真熱鬧缩搅,春花似錦、人聲如沸触幼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至堂鲤,卻和暖如春亿傅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瘟栖。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工葵擎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人半哟。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓酬滤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親寓涨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盯串,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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

  • iOS目前已經(jīng)是ARC 時(shí)代奏司。但對(duì)于要想了解ARC的內(nèi)存管理機(jī)制,還是依舊需要對(duì)MRC時(shí)代的內(nèi)存管理機(jī)制有深刻的理...
    ivylee_mr閱讀 1,744評(píng)論 0 2
  • 1. 內(nèi)總管理原則(引用計(jì)數(shù)) IOS的對(duì)象都繼承于NSObject, 該對(duì)象有一個(gè)方法:retainCount...
    lilinjianshu閱讀 2,151評(píng)論 0 2
  • 內(nèi)存管理 簡(jiǎn)述OC中內(nèi)存管理機(jī)制樟插。與retain配對(duì)使用的方法是dealloc還是release韵洋,為什么?需要與a...
    丶逐漸閱讀 1,950評(píng)論 1 16
  • iOS開(kāi)發(fā)中, 之前一直使用swift, 因此對(duì)于Objective-C的內(nèi)存管理機(jī)制長(zhǎng)期處于混亂的一知半解狀態(tài)....
    icetime17閱讀 839評(píng)論 1 8
  • 內(nèi)存管理是程序在運(yùn)行時(shí)分配內(nèi)存黄锤、使用內(nèi)存搪缨,并在程序完成時(shí)釋放內(nèi)存的過(guò)程。在Objective-C中鸵熟,也被看作是在眾...
    蹲瓜閱讀 3,025評(píng)論 1 8