亚洲免费不卡_在线视频精品_国产尤物精品_久久久久网址_久久精品91_欧美va天堂在线_狠狠入ady亚洲精品_亚洲午夜精品福利_国产精品草草_午夜精品久久99蜜桃的功能介绍

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

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

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

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

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

什么時候使用retain?

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

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

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

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

自動釋放

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

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

例子:

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];

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

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

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能夠擊發垃圾回收器釋放內存。

返回一個對象的指針

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

錯誤的方法:

- (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內存管理指南中的規則,盡管它不會泄露內存但是這樣做不好,因為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函數必須保留它所存儲的對象,也就是聲明所有權。如果我們想要創建一個 setter 函數,我們需要在分配一個新的指向成員變量的指針之前做兩件事情。

在函數里:

- (void) setname:(nsstring*)newname

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

[name release];

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

然后我們增加新的 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 來釋放對象可能是危險,可能會觸發一些想不到的事情。在出口處,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 函數之間的對象。

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

- (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 結束。

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

[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);

}

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

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

更多信息請查看技術文章
易賢網手機網站地址:如何避免iphone應用中內存泄露
由于各方面情況的不斷調整與變化,易賢網提供的所有考試信息和咨詢回復僅供參考,敬請考生以權威部門公布的正式信息和咨詢為準!
關于我們 | 聯系我們 | 人才招聘 | 網站聲明 | 網站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點

版權所有:易賢網

亚洲免费不卡_在线视频精品_国产尤物精品_久久久久网址_久久精品91_欧美va天堂在线_狠狠入ady亚洲精品_亚洲午夜精品福利_国产精品草草_午夜精品久久99蜜桃的功能介绍
在线亚洲美日韩| 国产精品乱子乱xxxx| 在线看片一区| 一区二区日韩免费看| 亚洲一区亚洲| 欧美国产三区| 妖精视频成人观看www| 国产精品日韩欧美一区| 欧美日韩成人一区二区三区| 伊人狠狠色j香婷婷综合| 国产精品呻吟| 亚洲午夜精品久久久久久app| 一本色道久久综合亚洲精品婷婷| 亚洲在线不卡| 亚洲三级观看| 欧美a级片网站| 国产精品欧美久久| 狠狠色噜噜狠狠色综合久 | 亚洲二区三区四区| 久久综合福利| 国产精品一区二区三区观看| 精品白丝av| 欧美激情视频一区二区三区免费| 国产欧美一级| 亚洲国产精品久久久久久女王| 久久久久国产精品一区三寸| 一本色道久久| 日韩五码在线| 亚洲狠狠婷婷| 中日韩男男gay无套| 伊人久久大香线蕉综合热线| 亚洲一区激情| 国产精品毛片| 国产伦精品一区二区三区视频孕妇 | 久久久久99| 亚洲国内在线| 亚洲图片欧洲图片日韩av| 欧美一区二区三区免费看| 免费视频一区| 久久激情综合| 久久久久国产一区二区| 欧美专区18| 久久精品1区| 久久久久久久尹人综合网亚洲| 国产欧美不卡| 国产精品免费看| 欧美一级久久| 久久久久国产精品一区三寸| 久久国产精品亚洲77777| 亚洲欧美日韩国产一区二区| 国产日韩三区| 亚洲一区欧美二区| 六月婷婷久久| 欧美日韩国产精品一卡| 欧美深夜福利| 亚洲国产精品一区二区第一页| 极品少妇一区二区三区| 亚洲黄色成人| 久久国产精品99国产| 你懂的视频一区二区| 午夜精品亚洲| 亚洲黄色视屏| 麻豆久久久9性大片| 亚洲影视在线| 欧美成人亚洲| 在线日本高清免费不卡| 99在线|亚洲一区二区| a91a精品视频在线观看| 国产农村妇女毛片精品久久莱园子 | 海角社区69精品视频| 狠狠色狠狠色综合日日tαg| 99精品国产福利在线观看免费| 亚洲视频1区| 欧美日韩免费观看一区=区三区| 国产专区一区| 国产欧美亚洲一区| 欧美在线播放一区| 亚洲精品影院| 欧美日韩福利| 一区二区三区四区国产| 久久亚洲高清| 欧美激情第六页| 在线亚洲伦理| 久久久国产精品一区二区中文 | 亚洲欧美日韩视频二区| 欧美日韩99| 亚洲一区二区三区高清不卡| 欧美日韩亚洲三区| 久久xxxx| 国产日本精品| 黄色成人在线网址| 欧美在线影院| 国产精品五区| 亚洲啪啪91| 亚洲天堂久久| 欧美va天堂在线| 在线亚洲国产精品网站| 国产精品二区三区四区| 欧美亚洲免费| 国产伦精品一区二区三区照片91 | 六月天综合网| 亚洲国内欧美| 一区在线视频| 国模吧视频一区| 欧美二区视频| 西西裸体人体做爰大胆久久久| 悠悠资源网久久精品| 欧美日韩天天操| 欧美高清日韩| 欧美在线视频二区| 久久伊人亚洲| 久久在线精品| 欧美福利影院| 欧美精品尤物在线| 国产精品国产三级国产专区53| 欧美福利网址| 欧美日韩国产免费观看 | 久久久久久一区二区| 国产精品一区二区a| 日韩亚洲国产欧美| 中文亚洲欧美| 鲁鲁狠狠狠7777一区二区| 国产九九精品| 久久成人资源| 欧美人与禽猛交乱配视频| 欧美精品一区二区三区在线看午夜 | 噜噜噜噜噜久久久久久91| 在线视频观看日韩| 一区在线电影| 国产亚洲一级| 美女久久一区| 欧美午夜一区| av成人国产| 免费亚洲婷婷| 欧美午夜国产| 亚洲三级观看| 乱码第一页成人| 欧美日韩ab| 日韩一区二区久久| 久久久噜噜噜| 激情婷婷久久| 亚洲一区精品视频| 欧美日韩一区在线观看视频| 亚洲激情网站| 另类亚洲自拍| 韩日精品在线| 国产日韩一区二区三区在线| 亚洲一区二区三区四区中文| 老司机精品久久| 亚洲精品婷婷| 狼狼综合久久久久综合网| 尤物精品在线| 久久一区二区精品| aa亚洲婷婷| 国内一区二区三区| 久久国产精品99国产| 亚洲午夜在线| 欧美 日韩 国产 一区| 日韩视频精品| 欧美日韩综合网| 性高湖久久久久久久久| 精品99视频| 欧美激情综合色综合啪啪| 一区在线播放| 在线一区欧美| 欧美深夜福利| 久久久久久穴| 午夜在线精品偷拍| 亚洲精品四区| 在线播放亚洲| 欧美日韩三区| 欧美激情麻豆| 欧美高清一区| 欧美成人高清| 麻豆成人精品| 亚洲一区观看| 国产深夜精品| 国产精品久久久久久久免费软件| 欧美黄色一区二区| 久久精品国产清高在天天线| 国产精品一区二区在线观看| 一区二区日本视频| 一本色道久久综合亚洲精品不| 激情国产一区| 黄色日韩精品| 激情久久久久久| 亚洲视频综合| 亚洲午夜黄色| 亚洲国产午夜| 亚洲精品一二| 一区二区三区四区五区在线 | 亚洲精品男同| 日韩亚洲不卡在线| 久久亚洲图片| 欧美在线视频二区| 欧美国内亚洲| 欧美色图首页| 伊人久久久大香线蕉综合直播| 欧美亚韩一区| 伊人蜜桃色噜噜激情综合| 亚洲第一伊人| 亚洲国产日韩在线| 国产日韩欧美一区| 欧美专区18| 毛片一区二区| 国产日韩欧美一区二区三区在线观看 | 免费国产自线拍一欧美视频| 国产亚洲精品久久飘花 | 欧美日韩国产成人精品| 国产精品mv在线观看| 激情久久五月| 国产精品最新自拍| 欧美91视频| 亚洲精品孕妇| 久久久水蜜桃av免费网站| 欧美激情四色| 99热免费精品| 久久久噜噜噜| 一区在线视频| 性伦欧美刺激片在线观看| 巨乳诱惑日韩免费av| 在线看无码的免费网站| 国产精品主播| 黄色在线成人| 久久xxxx精品视频| 一区二区视频在线观看| 亚洲女同在线| 伊人成人网在线看| 久久久久99| 99综合视频| 国内自拍一区| 久久综合导航| 国产亚洲一区在线播放| 国产在线一区二区三区四区| 国产农村妇女精品一区二区| 国内成+人亚洲| 久久久久综合| 国产农村妇女毛片精品久久莱园子 | 国内精品嫩模av私拍在线观看| 亚洲激情视频| 欧美日韩福利| 久久国产精品一区二区三区| 亚洲高清网站| 欧美日韩一区二区三区在线观看免 | 午夜电影亚洲| 国产精品社区| 亚洲精品一品区二品区三品区| 久久久蜜桃一区二区人| 一区二区日韩免费看| 国内精品久久国产| 午夜精品亚洲| 欧美尤物一区| 麻豆成人在线| 久久激情一区| 久久久精品网| 久久精品人人| 久久激情一区| 久久成人国产| 国产伦精品一区二区三区视频黑人 | 女生裸体视频一区二区三区| 在线综合亚洲| 亚洲精品在线视频观看| 在线视频国内自拍亚洲视频| 亚洲视频综合| 国产精品国码视频| 欧美日韩视频在线一区二区观看视频 | 午夜精品亚洲| 欧美日韩18| 很黄很黄激情成人| 伊人久久大香线蕉综合热线| 影音先锋一区| 亚洲精品影视| 亚洲一区不卡| 老司机精品福利视频| 欧美精品播放| 国产综合欧美| 日韩视频在线播放| 国产精品一区二区三区四区五区| 国产私拍一区| 久久激情久久| 欧美视频1区| 亚洲理论在线| 欧美精品激情| 欧美特黄视频| 亚洲第一黄网| 中文高清一区| 久久只有精品| 禁久久精品乱码| 99国产精品久久久久久久| 99热这里只有精品8| 亚洲欧美日产图| 午夜精品影院| 亚洲欧洲精品一区| 免费试看一区| 韩日视频一区| 亚洲一区日韩| 国产一区自拍视频| 国产亚洲欧美另类一区二区三区| 久久久久久久久一区二区| 黄色成人在线网站| 午夜在线播放视频欧美| 黄色日韩在线| 久久精品欧美| 9色精品在线| 国语精品中文字幕| 麻豆91精品| 99视频+国产日韩欧美| 欧美激情1区2区3区| 一区二区三区偷拍| 欧美日韩岛国| 久久激情网站| 国产精品免费在线| 激情久久久久久| 久久亚洲视频| 国产精品日韩欧美一区| 精品av久久久久电影| 女女同性女同一区二区三区91 | 中文欧美日韩| 欧美色123| 久久久久久精| 国产伦一区二区三区色一情| 亚洲婷婷在线| 欧美日韩亚洲一区二区三区四区| 国产亚洲在线观看| 91久久精品国产91久久性色tv | 国产精品日韩一区二区三区| 黄色成人av网站| 国产精品99一区二区| 欧美ab在线视频| 久久亚洲色图| 欧美久久一区| 久久久久综合| 国产精品一区二区三区四区五区| 在线播放不卡| 狠狠综合久久| 亚洲先锋成人| 亚洲特级毛片| 极品尤物久久久av免费看| 国内精品福利| 在线播放精品| 亚洲人成人一区二区三区| 在线看片日韩| 一本色道久久综合亚洲精品不卡| 亚洲欧洲久久| 国产视频亚洲| 亚洲在线免费| 久久免费一区| 欧美日韩天天操| 国内精品久久国产| 悠悠资源网久久精品| 亚洲国产国产亚洲一二三| 狠狠综合久久| 一区二区三区福利| 性8sex亚洲区入口| 欧美影院一区| 国产一区视频观看| 亚洲国产日韩欧美| 国产精品永久入口久久久| 久久精品日产第一区二区 | 91久久亚洲| 国产伦精品一区二区三区高清版 | 激情自拍一区| 国产日韩精品视频一区二区三区| 国产日韩欧美亚洲一区| 久久精品中文| 国产在线观看一区| 一区二区国产精品| 久久久噜噜噜| 激情欧美一区| 国产精品久久久久久久久久直播 | 午夜欧美视频| 日韩午夜av在线| 欧美一区影院| 91久久黄色| 久久看片网站| 亚洲欧洲另类| 欧美精品一级| 国产日韩一区欧美| 欧美日韩一视频区二区| 国产欧美另类| 欧美亚洲不卡| 久久国产精品一区二区三区四区| 激情久久中文字幕| 久久久综合香蕉尹人综合网| 亚洲久久一区二区| 国产亚洲精品v| 欧美日韩国产精品一区二区亚洲 | 久久婷婷麻豆| 亚洲免费成人| 欧美精品麻豆| 国产欧美69| 一区二区视频欧美| 久久人人精品| 国产伦精品一区二区三区照片91 | 亚洲一级电影| 久久综合一区二区三区| 国产一区二区久久久| 很黄很黄激情成人| 欧美精品一区二区三区久久久竹菊| 国产欧美高清|