中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久

如何避免iphone應用中內存泄露
來源:易賢網 閱讀:1156 次 日期:2015-03-12 14:18:09
溫馨提示:易賢網小編為您整理了“如何避免iphone應用中內存泄露”,方便廣大網友查閱!

創(chuàng)建對象時,所有權通過alloc、new、或者copy的方式建立,之后通過調用retain或者通過cocoa函數來分配和復制對象的所有權。 內存釋放有兩種方式,一種方法是明確地請求釋放對象的所有權,另一種方法則是使用自動釋放池(auto-release pool)。

所有權的背后是一個和引用有關的運算系統,iphone sdk的大多數對象使用這個系統,彼此之間建立著很強的引用和參照。

當你創(chuàng)建一個對象時,引用值為1,調用一次retain則對象的引用值加1,調用一次release則對象的引用值減1,當引用值為0時,對象的所有權分配將被取消。使用自動釋放池意味著對象的所有權將在一段延后的時間內被自動取消。

對象之間也可以建立弱的引用參照,此時意味著,引用值不會被保留,對象的分配需要手動取消。

什么時候使用retain?

什么時候你想阻止對象在使用前就被釋放?

每當使用copy、alloc、retain、或者cocoa函數來創(chuàng)建和復制所有權,你都需要相應的release或者auto-release。

開發(fā)者應該從所有權的角度來考慮對象,而不必擔心引用值。只要你有相應的retain和release方法,就能夠對引用值進行+1和-1操作。

注意:你或許想使用[object retaincount],但它可能因為sdk的底層代碼而發(fā)生返回值出錯的情況。在內存管理時不推薦這種方式。

自動釋放

將對象設置為自動釋放意味著不需要明確地請求釋放,因為當自動釋放池清空時它們將被自動釋放。iphone在主線程上運行自動釋放池,能夠在事件循環(huán)結束后釋放對象。當你創(chuàng)建你自己的線程時,你需要創(chuàng)建自己的自動釋放池。

iphone上有便利的構造函數,用這種方法創(chuàng)建的對象會設置為自動釋放。

例子:

nsstring* str0 = @hello;

nsstring* str1 = [nsstring stringwithstring:@world];

nsstring* str2 = str1;

一個已分配的對象可以用如下的方法設置為自動釋放:

nsstring* str = [[nsstring alloc] initwithstring:@the flash?];

[str autorelease];

或者用下面的方法:

nsstring* str = [[[nsstring alloc] initwithstring:@batman!] autorelease];

當指針出界,或者當自動釋放池清空時,自動釋放對象上的所有權將被取消。

在一個事件循環(huán)結束時,自動釋放池內的構件通常會被清空。但是當你的循環(huán)每次迭代都分配大量內存時,你或許希望這不要發(fā)生。這種情況下,你可以在循 環(huán)內創(chuàng)建自動釋放池。自動釋放池可以嵌套,所以內部池清空時,其中分配的對象將被釋放。在下面的例子中,每次迭代后將釋放對象。

for (int i = 0; i < 10; ++i)

{

nsautoreleasepool *pool = [[nsautoreleasepool alloc] init];

nsstring* str = [nsstring stringwithstring:@hello world];

[self processmessage: str];

[pool drain];

}

注意:在編寫的時候iphone不支持垃圾回收,所以drain和release的功能相同。當你想為程序設置osx的端口時通常會使用drain,除非后來在iphone中添加了垃圾回收機制。drain能夠擊發(fā)垃圾回收器釋放內存。

返回一個對象的指針

開發(fā)者在遵循所有權規(guī)則時需要清楚哪些函數擁有對象的所有權。下面是返回一個對象的指針并釋放的例子。

錯誤的方法:

- (nsmutablestring*) getoutput

{

nsmutablestring* output = [[nsmutablestring alloc] initwithstring:@output];

return output;

}

- (void) test

{

nsmutablestring* obj = [self getoutput];

nslog(@count: %d, [obj retaincount]);

[obj release];

}

在這個例子中,output 的所有者是 getoutput,讓 test 釋放 obj 違反了coccoa內存管理指南中的規(guī)則,盡管它不會泄露內存但是這樣做不好,因為test 不應該釋放并非它所擁有的對象。

正確的方法:

- (nsmutablestring*) getoutput

{

nsmutablestring* output = [[nsmutablestring alloc] initwithstring:@output];

return [output autorelease];

}

- (void) test

{

nsmutablestring* obj = [self getoutput];

nslog(@count: %d, [obj retaincount]);

}

在第二個例子中,output 被設置為當 getoutput 返回時自動釋放。output的引用值減少,getobject 釋放 output 的所有權。test 函數現在可以自由的 retain 和 release 對象,請確保它不會泄露內存。

例子中 obj 被設置為自動釋放,所以 test 函數沒有它的所有權,但是如果它需要在其他地方存儲對象會怎樣?

此時對象需要有一個新的所有者來保留。

setters

setter函數必須保留它所存儲的對象,也就是聲明所有權。如果我們想要創(chuàng)建一個 setter 函數,我們需要在分配一個新的指向成員變量的指針之前做兩件事情。

在函數里:

- (void) setname:(nsstring*)newname

首先我們要減少成員變量的引用值:

[name release];

這將允許當引用值為0時 name 對象被釋放,但是它也允許對象的其他所有者繼續(xù)使用對象。

然后我們增加新的 nsstring 對象的引用值:

[newname retain];

所以當 setname 結束時, newname 不會被取消分配。 newname 現在指向的對象和 name 指向的對象不同,兩者有不同的引用值。

現在我們設置 name 指向 newname 對象:

name = newname;

但是如果 name 和 newname 是同一個對象時怎么辦?我們不能在它被釋放后保留它,并再次釋放。

在釋放存儲的對象前保留新的對象:

[newname retain];

[name release];

name = newname;

現在兩個對象是相同的,先增加它的引用值,然后再減少,從而使得賦值前引用值不變。

另一種做法是使用 objective-c:

聲明如下:

@property(nonatomic, retain) nsstring *name;

1. nonatomic 表示沒有對同一時間獲取數據的多個線程進行組塊兒。atomic 為一個單一的線程鎖定數據,但因為 atomic 的方式比較緩慢,所以不是必須的情況一般不使用。

2. retain 表示我們想要保留 newname 對象。

我們可以使用 copy 代替 retain:

@property(nonatomic, copy) nsstring *name;

這和下面的函數一樣:

- (void) setname:(nsstring*)newname

{

nsstring* copiedname = [newname copy];

[name release];

name = copiedname;

[name retain];

[copiedname release];

}

newname 在這里被復制到 copiedname,現在 copiedname 擁有串的一個副本。name 被釋放,而 copiedname 被賦給 name。之后 name 保留這個串,從而使得 copiedname 和 name 同時擁有它。最后 copiedname 釋放這個對象,name 成為這個串的唯一所有者。

如果我們有如下的函數,像這樣的 setters 將被輸入用來保留成員對象:

- (void) test

{

nsautoreleasepool *pool = [[nsautoreleasepool alloc] init];

// do something...

name = [self getoutput];

// do something else...

nslog(@client name before drain: %@, name);

[pool drain];

nslog(@client name after drain: %@, name);

}

name 在調用至 drain 后是未定義的,因為當池被釋放時,name 也將被釋放。

如果我們用如下的部分替代賦值:

[self setname:[self getoutput]];

然后 name 將被這個類所有,在使用時保留直到調用 release

那么我們何時釋放對象?

由于 name 是成員變量,釋放它的最安全的辦法是對它所屬的類使用 dealloc 函數。

- (void)dealloc

{

[name release];

[super dealloc];

}

注意:雖然并不總是調用 dealloc,依靠 dealloc 來釋放對象可能是危險,可能會觸發(fā)一些想不到的事情。在出口處,iphone os 可能在調用 dealloc 前清空全部應用程序的內存。

當用 setter 給對象賦值時,請小心下面的語句:

[self setname:[[nsstring alloc] init]];

name 的設置是正確的但 alloc 沒有相應的釋放,下面的方式要好一些:

nsstring* s = [[nsstring alloc] init];

[self setname:s];

[s release];

或者使用自動釋放:

[self setname:[[[nsstring alloc] init] autorelease]];

自動釋放池

自動釋放池釋放位于分配和 drain 函數之間的對象。

我們在下面的函數中設置一個循環(huán),在循環(huán)中將 nsnumber 的一個副本賦給 magicnumber,另外將 magicnumber 設置為自動釋放。在這個例子中,我們希望在每次迭代時清空自動釋放池(這樣可以在賦值的數量很大時節(jié)省循環(huán)的內存)

- (void) test

{

nsstring* clientname = nil;

nsnumber* magicnumber = nil;

for (int i = 0; i < 10; ++i)

{

nsautoreleasepool *pool = [[nsautoreleasepool alloc] init];

magicnumber = [[self getmagicnumber] copy];

[magicnumber autorelease];

if (i == [magicnumber intvalue])

{

clientname = [self getoutput];

}

[pool drain];

}

if (clientname != nil)

{

nslog(@client name: %@, clientname);

}

}

這里存在的問題是 clientname 在本地的自動釋放池中被賦值和釋放,所以當外部的池清空時,clientname 已經被釋放了,任何對 clientname 的進一步使用都是沒有定義的。

在這個例子中,我們在賦值后保留 clientname,直到結束時再釋放它:

- (void) test

{

nsstring* clientname = nil;

nsnumber* magicnumber = nil;

for (int i = 0; i < 10; ++i)

{

nsautoreleasepool *pool = [[nsautoreleasepool alloc] init];

magicnumber = [[self getmagicnumber] copy];

[magicnumber autorelease];

if (i == [magicnumber intvalue])

{

clientname = [self getoutput];

[clientname retain];

}

[pool drain];

}

if (clientname != nil)

{

nslog(@client name: %@, clientname);

[clientname release];

}

}

我們在調用 retain 函數和 release 函數的期間獲得 clientname 的所有權。通過添加一對 retain 和 release 的調用,我們就確保 clientname 在明確調用釋放前不會被自動釋放。

集合

當一個對象被添加進集合時,它就被集合所擁有。在這個例子中我們分配一個串,它現在有了所有者;

nsstring* str = [[nsstring alloc] initwithstring:@bruce wayne];

然后我們將它添加進數組,現在它有兩個所有者:

[array addobject: str];

我們可以安全的釋放這個串,使其僅被數組所有:

[str release];

當一個集合被釋放時,其中的所有對象都將被釋放。

nsmutablearray* array = [[nsmutablearray alloc] init];

nsstring* str = [[nsstring alloc] initwithstring:@bruce wayne];

[array addobject: str];

[array release];

在上面的例子中,我們分配了一個數組和一個串,然后將串添加到數組中并釋放數組。這使得串僅擁有一個所有者,并且在我們調用 [str release] 前它不會被釋放。

用線程傳遞指針

在這個函數中,我們從串的 input 傳遞到函數 dosomething,然后釋放 input

- (void) test

{

nsmutablestring* input = [[nsmutablestring alloc] initwithstring:@batman!];

[nsthread detachnewthreadselector:@selector(dosomething:) totarget:self withobject:input];

[input release];

}

detatchnewthreadselector 增加 input 對象的引用值并在線程結束時釋放它。這就是為什么我們能夠在線程剛開始的時候就釋放 input,而無論函數 dosomething 何時開始或結束。

- (void) dosomething:(nsstring*)str

{

[self performselectoronmainthread:@selector(finishsomething:) withobject:str waituntildone:false];

}

performseclectoronmainthread 也會保留傳遞的對象,直到 selector 結束。

自動釋放池是特殊的線程,所以如果我們在一個新的線程上創(chuàng)建自動釋放的對象,我們需要創(chuàng)建一個自動釋放池來釋放它們。

[nsthread detachnewthreadselector:@selector(process) totarget:self withobject:nil];

這里在另一個線程上調用函數 process

- (void) process

{

nsautoreleasepool *pool = [[nsautoreleasepool alloc] init];

nsmutablestring* output = [[[nsmutablestring alloc] initwithstring:@batman!] autorelease];

nslog(@output: %@, output);

[self performselectoronmainthread:@selector(finishprocess) withobject:nil waituntildone:false];

[pool drain];

}

對象 output 被分配并且在自動釋放池中設置了自動釋放,它將在函數結束前被釋放。

- (void) finishprocess

{

nsmutablestring* output = [[[nsmutablestring alloc] initwithstring:@superman?] autorelease];

nslog(@output: %@, output);

}

系統會為主線程自動創(chuàng)建一個自動釋放池,所以在 finishprocess 中,我們不需要為主線程上運行的函數創(chuàng)建自動釋放池。

更多信息請查看IT技術專欄

更多信息請查看技術文章
易賢網手機網站地址:如何避免iphone應用中內存泄露

2026上岸·考公考編培訓報班

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關于我們 | 聯系我們 | 人才招聘 | 網站聲明 | 網站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網安備53010202001879號 人力資源服務許可證:(云)人服證字(2023)第0102001523號
聯系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權所有:易賢網
中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久
国产精品日韩精品| 国产在线精品一区二区夜色| 国产精品一区二区三区观看| 亚洲欧美高清| 精品成人国产| 国际精品欧美精品| 国产精品久久久亚洲一区| 欧美日韩中文| 欧美成人久久| 欧美午夜免费电影| 国产在线不卡视频| 亚洲精品婷婷| 西西裸体人体做爰大胆久久久| 亚洲女人小视频在线观看| 欧美有码视频| 欧美日韩第一区日日骚| 亚洲国产精品精华液2区45| 亚洲网站视频福利| 欧美连裤袜在线视频| 亚洲国产乱码最新视频| 亚洲欧美日产图| 久久亚洲一区| 欧美午夜一区二区三区免费大片| 国产自产精品| 国产精品伦理| 亚洲电影自拍| 欧美在线网站| 国产精品福利久久久| 136国产福利精品导航| 久久色在线观看| 尤物yw午夜国产精品视频| 日韩天天综合| 欧美色123| 欧美一区二区日韩| 国产亚洲精品自拍| 久久男女视频| 亚洲激情啪啪| 国产午夜精品福利| 99国产麻豆精品| 国产精品v欧美精品v日韩精品 | 一区二区三区www| 国产精品对白刺激久久久| 亚洲中无吗在线| 欧美日韩久久| 午夜激情亚洲| 国产综合欧美在线看| 欧美在线视频免费观看| 国产一区二区毛片| 欧美国产欧美综合 | 欧美怡红院视频| 国产欧美va欧美va香蕉在| 久久青草欧美一区二区三区| 国产精品午夜电影| 欧美在线观看一二区| 欧美精品18+| 亚洲欧洲另类| 性刺激综合网| 国产欧美日韩在线观看| 亚洲美女啪啪| 国产精品一区二区a| 亚洲国产cao| 极品尤物久久久av免费看| 制服诱惑一区二区| 欧美精品二区| 尤物99国产成人精品视频| 亚洲欧美日韩另类| 国产伦精品一区二区三区免费迷 | 国产精品九九| 久热re这里精品视频在线6| 韩国成人精品a∨在线观看| 久久久久.com| 一区二区三区欧美成人| 极品尤物一区二区三区| 欧美二区在线| 日韩视频在线观看国产| 国产精品久久久爽爽爽麻豆色哟哟| 亚洲国产清纯| 国产精品一区二区在线| 麻豆freexxxx性91精品| 亚洲视频观看| 亚洲激情一区二区三区| 欧美日韩高清不卡| 亚洲午夜电影网| 亚洲视频在线观看三级| 国产精品午夜春色av| 久久天堂精品| 翔田千里一区二区| 亚洲黄网站黄| 国产精品www994| 欧美巨乳在线| 久久综合影音| 久久都是精品| 亚洲精品乱码久久久久久蜜桃91| 国产人成精品一区二区三| 欧美激情国产精品| 亚洲午夜一区| 亚洲高清一二三区| 国内精品视频在线播放| 国产精品男人爽免费视频1| 欧美片第1页综合| 欧美日韩国产综合在线| 欧美成人免费观看| 蜜臀av国产精品久久久久| 欧美在线观看视频一区二区三区 | 欧美性久久久| 欧美精品一区视频| 欧美不卡视频一区| 牛牛国产精品| 欧美性生交xxxxx久久久| 欧美激情片在线观看| 久久在线免费观看| 免费成人网www| 国产精品福利在线| 国产亚洲人成网站在线观看| 伊人久久男人天堂| 久久久久国色av免费观看性色| 国产精品美女| 亚洲精品综合精品自拍| 一区二区三区www| 欧美一二三区在线观看| 欧美大片网址| 国产一区日韩一区| 亚洲欧洲av一区二区| 欧美激情亚洲国产| 欧美精品一区二区三区蜜臀| 欧美日韩福利视频| 在线欧美日韩国产| 99精品热视频只有精品10| 欧美精品 国产精品| 激情欧美日韩| 日韩图片一区| 欧美精品午夜| 国产在线一区二区三区四区| 在线日韩av片| 久久福利视频导航| 国产亚洲欧美一区二区| 日韩一区二区精品葵司在线| 欧美日韩精品免费在线观看视频| 日韩午夜av在线| 欧美性大战久久久久久久| 亚洲欧美资源在线| 国产在线观看一区| 欧美1区2区3区| 亚洲一区久久久| 国产精品视频久久一区| 久久精品五月| 日韩午夜电影在线观看| 欧美精品 日韩| 欧美在线www| 亚洲伦理在线| 国产亚洲成年网址在线观看| 欧美成年人视频网站欧美| 亚洲在线国产日韩欧美| 精品二区久久| 欧美午夜精品久久久久久人妖| 亚洲欧美激情视频| 极品少妇一区二区| 国产精品综合| 欧美日韩国产精品| 午夜精品一区二区三区四区| 日韩一区二区精品葵司在线| 欧美波霸影院| 99精品欧美一区二区三区综合在线| 欧美特黄一区| 蜜桃精品久久久久久久免费影院| 亚洲午夜电影网| 99香蕉国产精品偷在线观看| 有码中文亚洲精品| 国产欧美日韩在线| 国产美女扒开尿口久久久| 欧美午夜a级限制福利片| 美日韩精品免费| 欧美国产1区2区| 欧美久久久久| 亚洲欧洲日本国产| 亚洲国产经典视频| 国产美女一区| 国产欧美一区二区三区在线老狼 | 欧美精品午夜| 久久久久一区| 久久偷看各类wc女厕嘘嘘偷窃| 99re6这里只有精品| 亚洲三级电影全部在线观看高清| 国内精品视频在线播放| 国产精品主播| 欧美午夜电影网| 欧美理论电影在线播放| 欧美日产一区二区三区在线观看| 久久精品欧洲| 久久久综合香蕉尹人综合网| 欧美大香线蕉线伊人久久国产精品| 免费观看日韩| 国产乱码精品一区二区三区忘忧草 | 欧美色区777第一页| 欧美国产欧美亚洲国产日韩mv天天看完整 | 日韩午夜电影av| 美腿丝袜亚洲色图| 国产嫩草一区二区三区在线观看| 亚洲日本中文| 男人的天堂亚洲在线|