2012-11-29 76 views
0

在Objective C中,我如何顯式釋放由另一個對象擁有的對象?或者也許等價地告知擁有的對象它不再擁有子對象。考慮以下幾點:如何釋放目標C中其他對象擁有的對象C

- (void) testWithNSString:(NSString *)val 
{ 
    NSData *data = [val dataUsingEncoding:NSASCIIStringEncoding]; 
    // ... 
    // now I want to explicitly release data e.g. due to low memory 
} 

[val dataUsingEncoding:NSASCIIStringEncoding]一個NSData對象返回,我以爲(由於所有權的一般慣例),它會被釋放,當val被釋放。從不泄漏的角度來看這似乎是可以接受的。但是這個策略引發了兩個問題:

  1. 如果我想立即明確釋放data對象,由於內存不足?
  2. 如果我不想讓testWithNSString的調用者留下NSString val對象(在testWithNSString已返回之後),它突然擁有新對象的所有權?
+0

只要你不分配內存,你不必擔心,因爲操作系統會照顧它。遇到內存不足時,無論如何都會釋放這些參數。當你從這個方法返回時,所有的局部變量將被釋放。 – iDev

+0

@ACB我不這麼認爲。 'dataUsingEncoding:'返回一個自動發佈的'NSData'。它將在運行循環結束時釋放,而不是從方法返回時釋放。 – DrummerB

+0

@DrummerB,Yup。我沒有直接提到它。我的觀點是,他不必擔心永遠留在記憶中。 autorelease的實際工作是你所提到的。 – iDev

回答

1

在[VAL dataUsingEncoding:NSASCIIStringEncoding]一個NSData對象返回和我假定(由於所有權的一般慣例),它將被釋放,VAL被釋放時

這是不正確。 dataUsingEncoding將創建一個新的NSData對象,該對象與val(至生命週期)沒有任何關係。這是一個autoreleased對象,它將在運行循環的下一個循環中釋放(大約我們不知道),除非你保持它。

如果我想立即顯式釋放數據對象,例如由於內存不足?

如果你想立即釋放對象,並且使用的是ARC,你可以簡單地分配零到它的指針:

data = nil; 

如果你不使用ARC,你最好的選擇是等待運行循環自動釋放池來完成它的工作。或者你可以在你的方法中創建一個本地自動釋放池,這樣自動釋放的對象在方法結束時被排空,而不是在下一次運行循環中排空。這隻會在長時間運行的方法(或方法鏈)的情況下才有所作爲,所以我不知道在你的情況下是否有意義。

如果我不希望testWithNSString的調用者留下一個NSString val對象(在testWithNSString返回後),它突然擁有新對象的所有權?

正如我所說,val沒有data的所有權。

總結這一切,你的data對象是autoreleased,它會很快在你的方法結束後(除非它是一個長期運行的方法);所以data內存將被有效地恢復,我不會擔心它(除非它是一個長期運行的方法,正如我所說的)。

+0

這看起來不錯!這是否意味着我可以明確調用[數據發佈]? 有關Objective C文檔的一個大問題:我在哪裏可以找到返回的NSData對象不屬於接收方? –

+0

如果你正在使用ARC(你沒有指定,我不知道在哪種情況下推理),你不能完全使用'release';如果你不使用ARC,發送'release'到一個自動釋放對象會導致崩潰。你應該使用alloc/init來獲得'data'對象,然後你就是對象的所有者,並且可以發送'release'給它;我希望我已經清楚了...... – sergio

+1

@JakobBjerreJensen通常,如果你使用一個以類的名字開頭的類方法(比如'[NSData dataUsingEncoding:x]'),你會得到一個自動釋放對象。這是一個慣例,而且幾乎總是如此。如果不是,你會在文檔中被警告。如果你使用'alloc/init'或'copy'方法創建一個對象,你將永遠擁有這個對象。 – DrummerB

-1

假設您使用的是ARC,將val設置爲零應釋放它。

2

首先,你應該從來沒有永遠釋放你不擁有的對象。返回的NSData對象將在val發佈時釋放而不是。這兩個對象是完全獨立的(除了data來自val)。

dataUsingEncoding:返回自動釋放對象。這意味着data將在運行循環結束時發佈。

如果你是怕你會運行內存不足,並希望它早些時候發佈您可以使用NSAutoreleasePool池:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
NSData *data = [val dataUsingEncoding:NSASCIIStringEncoding]; 
// do something with data. 
[pool release]; 

這將釋放data當你釋放池。