2012-02-29 71 views
1

下面的代碼是從用來說明如何寫一個字符串到文件「的的iOS 5開發者的食譜」拍攝。它利用__autoreleasing沒有任何解釋。爲什麼有必要?使用代碼__autoreleasing的片斷例如

NSError __autoreleasing error; 
... 
if (![myString writeToFile:path atomically:YES error:&error) 
{ 
    NSLog(.... error.localizedFailureReason ...); 
    return; 
} 

爲什麼不直接在堆棧上聲明錯誤而不使用__autoreleasing?

------ -----編輯

另一個問題:爲什麼作者聲明NSError而不是NSError *?

回答

3

這對自動的引用計數(ARC)系統的暗示。

error對象將被分配到NSString代碼的某處,因此在代碼中聲明它爲__autoreleasing可以讓ARC知道存儲特性。也就是說,當設置了error時,它將是一個自動釋放對象。

+0

大多數時候NSError被聲明爲NSError *錯誤。但在這種情況下,它的NSError錯誤。即在wrieToFile之前創建NSError:這是否會產生後果? – Gruntcakes 2012-02-29 16:28:22

+0

我實際上用'NSError * error'提交了一個編輯到你原來的問題。我認爲這一定是本書中的一個錯字:Obj-C對象總是用指針引用,所以'NSError error'會給編譯時錯誤。 – gregheo 2012-02-29 17:05:17

+0

恐怕這個答案是不正確的。它不是「提示」,而是語義的聲明 - *提示*可以忽略,*語義*不可以。另外,存儲的引用不需要對自動釋放的對象進行存儲。請參閱[這個問題](http://stackoverflow.com/questions/8814718/handling-pointer-to-pointer-ownership-issues-in-arc)瞭解更多的背景知識。 – CRD 2014-04-22 18:54:06

0

嗯,這是一個ARC約定使用__autoreleasing預選賽按引用傳遞對象。 【解說】這裏離鐺網站:

4.3.2。 __autoreleasing的存儲持續時間的對象

是形成不良的一種程序,如果它聲明 非自動存儲持續時間的__autoreleasing對象。

理由:自動釋放池被綁定到其本質當前線程和範圍 。雖然可能有臨時對象,其 實例變量都充滿了自動釋放的對象,沒有 方式,ARC能提供任何安全保障的存在。

這是,如果一個非空指針被分配給 __autoreleasing對象,同時自動釋放池是在範圍上,然後自動釋放池的範圍離開後該對象被讀取未定義的行爲。

1

代碼:

__autoreleasing NSString *str = xx; 

將ARC被編譯爲:

NSString *str = xx.autorelease 
+0

沒有屬性的點語法不是最佳實踐。除此之外,它並沒有真正回答爲什麼在ARC – Binarian 2013-08-11 19:51:50

7

你失去了什麼,當一個變量通過引用傳遞,並在ARC計劃分配的實際情況在此代碼。舉例來說,一種功能(BOOL)保存:(NSError * __autoreleasing *)錯誤

在非ARC編程,保存功能如下:

- (BOOL)save:(NSError * __autoreleasing *)myError { 
    *myError = [[[NSError error] retain] autorelease] 
} 

在ARC編程,保存功能看起來像這樣的:

- (BOOL)save:(NSError * __autoreleasing *)myError { 
    *myError = [[NSError alloc] init]; 
} 

儘管ARC的代碼是什麼樣子,既保存功能創建已保留並自動釋放一個錯誤的對象。

這是因爲在ARC版本中,myError指針的類型決定了錯誤對象的內存管理會發生什麼情況。實際上,只要指針是類型__autoreleasing中,* myError分配線是替換

*myError = [[[NSError error] retain] autorelease] 

在運行時。

因此,如果我們能夠傳遞一個錯誤類型的指針,例如__strong保存函數,它會導致保存函數做錯誤的事情。

由於編譯器會通過創建一個臨時變量來防止這種情況發生,代碼將以任何方式工作,但傳遞一個非__autoreleasing類型的指針從ARC編程的角度來看是沒有意義的。

+0

中使用[xx autorelease]這是一個很好的答案,這是唯一真正解釋引擎蓋下發生的問題的答案之一。我還有一個額外的問題。爲什麼要傳遞給'save'的地址需要聲明爲'__autoreleasing'? ARC轉換指南說,否則會彈出一個臨時變量,但是編譯器不能對此做出明智的判斷?或者是否存在這個問題的語義原因? – Norswap 2013-11-27 10:36:41

+4

@Norswap試想一下,保存函數是預編譯庫的一部分。當你從保存功能返回時,ARC需要知道錯誤對象(** myError)是否已經在自動釋放池中。在這種情況下,通過查看保存功能的源代碼找不到它,因爲它沒有它。這是關於保存對ARC系統的輸入。當你這樣做時(例如)myDict = [NSDictionary dictionary]),你不需要同樣的東西的唯一原因是因爲嚴格約定,以這種方式返回的對象總是自動釋放。 – Colin 2013-12-02 18:20:34

+0

我想上面的評論更直接地回答OP的問題,而不是上面的答案。在回答這個問題時,我感興趣的是,ARC實際上是在程序員明確處理ARC之前做了與幕後相同的事情。它是智能編譯器的一部分,不屬於新的運行時引擎。 – Colin 2013-12-02 18:26:28