關(guān)于iOS內(nèi)存管理的規(guī)則思考
自己生成的生成的對(duì)象,自己持有。
非自己生成的對(duì)象,自己也能持有。
不在需要自己持有的對(duì)象時(shí)釋放。
非自己持有的對(duì)象無(wú)法釋放。
注:這里的自己是對(duì)象使用的環(huán)境,理解為編程人員本身也沒(méi)有錯(cuò)
對(duì)象操作和Objective-C方法對(duì)應(yīng)
| 對(duì)象操作 | Objectivew-C方法 | 
|---|---|
| 生成并持有對(duì)象 | alloc/copy/mutableCopy/new或以此開(kāi)頭的方法 | 
| 持有對(duì)象 | retain | 
| 釋放對(duì)象 | release | 
| 廢棄對(duì)象 | dealloc | 
自己生成的對(duì)象,自己持有
//自己生成并持有對(duì)象id obj1 = [[NSObject alloc] init];id obj2 = [NSObject new];id obj3 = [obj2 copy];
copy方法基于NSCopying方法約定,實(shí)現(xiàn)類(lèi)中的copyWithZone:
mutableCopy方法基于NSMutableCopying方法約定,實(shí)現(xiàn)類(lèi)中的mutableCopyWithZone:
非自己生成的對(duì)象,自己也能持有
用alloc/new/copy/mutableCopy以外的方法取得的對(duì)象,自己不是該對(duì)象的持有者。
//取的非自己生成并持有的對(duì)象,//取得對(duì)象的存在,但自己不持有對(duì)象。id obj = [NSMutableArray array];id obj2 = [NSDictionary dictionary];//自己持有對(duì)象[obj retain];[obj2 retain];
注:這里有點(diǎn)不好理解,我們先來(lái)看一段代碼:
//取的非自己生成并持有的對(duì)象,//取得對(duì)象的存在,但自己不持有對(duì)象。id unretain_obj = [NSMutableArray array];NSLog(@"unretain_obj retain count = %lu", (unsigned long)[unretain_obj retainCount]);//調(diào)用 release[unretain_obj release];
上述代碼,我們打印結(jié)果是:
2016-12-21 15:32:04.485 acm[65216:852108] unretain_obj retain count = 1
隨后調(diào)用release方法會(huì)導(dǎo)致程序崩潰!
按照引用計(jì)數(shù)來(lái)說(shuō),這時(shí)unretain_obj是可以被執(zhí)行一次release方法的。但是為什么我們直接調(diào)用會(huì)導(dǎo)致程序崩潰。
我們會(huì)想最開(kāi)始提到的四條思想之一:
無(wú)法釋放非自己持有的對(duì)象
這樣我們就很好理解了。雖然打印出unretain_obj的retainCount 為 1 但是不能說(shuō)明是因?yàn)樗昧藢?duì)象。它只是單純的獲取到了對(duì)象的存在而已。
那么我們會(huì)產(chǎn)生一個(gè)問(wèn)題。那么這個(gè)對(duì)象是誰(shuí)在持有??
我們先做一個(gè)猜測(cè):
因?yàn)閇NSMutableArray array]是一個(gè)工廠方法,在array肯定是要生成一個(gè)NSMutableArray實(shí)例對(duì)象。這時(shí)也必然會(huì)有一個(gè)指針引用它然后返回這個(gè)對(duì)象。so。。。
先想到這里,后邊我們?cè)偃ビ∽C
我們?cè)賮?lái)看一段代碼:
//取的非自己生成并持有的對(duì)象,//取得對(duì)象的存在,但自己不持有對(duì)象。id unretain_obj = [NSMutableArray array];NSLog(@"unretain_obj retain count = %lu", (unsigned long)[unretain_obj retainCount]);//自己持有對(duì)象[unretain_obj retain];NSLog(@"unretain_obj retain count = %lu", (unsigned long)[unretain_obj retainCount]);//釋放自己持有的對(duì)象[unretain_obj release];NSLog(@"unretain_obj retain count = %lu", (unsigned long)[unretain_obj retainCount]);
打印結(jié)果
	2016-12-21 15:40:20.774 acm[65682:861135] unretain_obj retain count = 1
	2016-12-21 15:40:20.774 acm[65682:861135] unretain_obj retain count = 2
	2016-12-21 15:40:25.254 acm[65682:861135] unretain_obj retain count = 1
并且程序也不會(huì)崩潰。
著也印證了我們上邊的想法。
因?yàn)橥ㄟ^(guò)retain方法,非自己生成的對(duì)象跟用alloc/new/copy/mutableCopy方法生成并持有的對(duì)象一樣,成了自己所持有的
不在需要自己持有的對(duì)象時(shí)釋放
通過(guò)上邊的例子我們知道,自己持有的對(duì)象在釋放時(shí)調(diào)用release方法,eg:
//自己生成并持有對(duì)象id release_obj = [[NSObject alloc] init];//將自己持有的對(duì)象釋放[release_obj release];/* * 釋放對(duì)象 * 指向?qū)ο蟮闹羔樢廊槐槐A粼谧兞縭elease_obj 中,你依然可以調(diào)用它。 * 但是對(duì)象一經(jīng)釋放絕對(duì)不可訪問(wèn),否則會(huì)造成程序崩潰。 * 出現(xiàn)EXC_BAD_ACCESS Crash問(wèn)題 */
我們自己實(shí)現(xiàn)一個(gè)方法,返回一個(gè)方法調(diào)用著也可以持有的對(duì)象,即alloc的作用
- (id)allocObject {   //自己生成并持有對(duì)象  id obj = [[NSObject alloc] init];  //原封不動(dòng)的返回一個(gè)由alloc方法生成的對(duì)象  return obj;注:方法名符合 生成并持有對(duì)象 alloc/copy/mutableCopy/new或以此開(kāi)頭的方法 規(guī)則
我們自己實(shí)現(xiàn)一個(gè)方法,返回一個(gè)誰(shuí)也不持有的對(duì)象,只是取得對(duì)象的存在
- (id)object {  //自己生成并持有對(duì)象  id obj = [[NSObject alloc] init];  //調(diào)用autorelease方法 取得對(duì)象的存在,但自己不持有對(duì)象。  [obj autorelease];  return obj;autorelease方法可以取得對(duì)象的存在,但自己不持有對(duì)象。使對(duì)象在超出指定的生存范圍時(shí)能夠自動(dòng)的并正確的釋放(調(diào)用release方法)
autorelease和release方法的區(qū)別
autorelease:
	
release:
	
autorelease的詳細(xì)解說(shuō)我們后邊介紹。
我們也可以通過(guò)調(diào)用retain方法來(lái)使 autorelease方法的來(lái)的對(duì)象自己持有eg:
//獲取對(duì)象的存在,自己不持有 id unretain_obj = [NSMutableArray array]; //持有對(duì)象[unretain_obj retain];
無(wú)法釋放非自己持有的對(duì)象
自己已經(jīng)釋放了還繼續(xù)釋放
//自己生成并持有對(duì)象 id release_obj = [[NSObject alloc] init]; //將自己持有的對(duì)象釋放 [release_obj release]; //釋放已經(jīng)釋放的對(duì)象 [release_obj release]; /* * 釋放對(duì)象 * 指向?qū)ο蟮闹羔樢廊槐槐A粼谧兞縭elease_obj 中,你依然可以調(diào)用它。 * 但是對(duì)象一經(jīng)釋放絕對(duì)不可訪問(wèn),否則會(huì)造成程序崩潰。 * 出現(xiàn)EXC_BAD_ACCESS Crash問(wèn)題 */
只獲取了對(duì)象的存在,試圖釋放對(duì)象
//取的非自己生成并持有的對(duì)象, //取得對(duì)象的存在,但自己不持有對(duì)象。 id unretain_obj = [NSMutableArray array]; //釋放自己不持有的對(duì)象 [unretain_obj release];
程序崩潰,報(bào)EXC_BAD_ACCESS Crash問(wèn)題
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注