2012-04-19 41 views
3

通過本書首先解釋這個問題(使用ARC)關於「unvalid」的引用,就像這個例子:我不明白強和弱引用

NSDate* date1=[[NSDate alloc]init]; 
NSDate* date2=date1; 
[date1 release]; 
NSLog(@"%@",date2); // bad access 

所以我理解了保留/釋放機制:在這種情況下,指令是:

date2=[date1 retain]; 

但是,當談到強/弱引用,這聽起來像一個矛盾,對我說:。

「默認情況下,引用是強喲如果你將一個對象分配給一個強大的引用,ARC假定你想讓這個對象堅持並隱含地保留它「

這不是與之前所說的矛盾嗎?
date2默認是強壯的,所以它應該隱式地保留date1,並且不會有一個不好的訪問異常。
當然我誤解了一些東西,有人能解釋這對我更好嗎?

回答

15

Strong是默認值,因爲它通常是您想要的,但使用ARC時,編譯器會分析對象的生命需要多長時間並在適當的時間釋放內存。例如:

- (void)someMethod 
{ 
    NSDate* date = [[NSDate alloc] init]; // date is __strong by default 
    NSLog(@"The date: %@", date); // date still contains the object created above 

    // Sometime before this point, the object date pointed to is released by the compiler 
} 

弱引用只保留對象,而它有一個或多個其他強引用。只要最後一個強引用被破壞,對象就會被編譯器釋放,並且運行時將弱對象引用(變量)更改爲nil。這使得弱變量在本地範圍內幾乎無用,就像上面的例子一樣。例如:

- (void)someMethod 
{ 
    __weak NSDate* date = [[NSDate alloc] init]; // The date created is released before it's ever assigned to date 
               // because date is __weak and the newly created date has no 
               // other __strong references 
    NSLog(@"The date: %@", date); // This always prints (null) since date is __weak 
} 

看到一個強和弱變量在局部範圍內一起工作的一個例子(這將只有非常有限的實用性和這裏真的是隻顯示演示變量引用弱):

- (void)someMethod 
{ 
    NSDate* date = [[NSDate alloc] init]; // date stays around because it's __strong 
    __weak NSDate* weakDate = date; 

    // Here, the dates will be the same, the second pointer (the object) will be the same 
    // and will remain retained, and the first pointer (the object reference) will be different 
    NSLog(@"Date(%p/%p): %@", &date, date, date); 
    NSLog(@"Weak Date(%p/%p): %@", &weakDate, weakDate, weakDate); 

    // This breaks the strong link to the created object and the compiler will now 
    // free the memory. This will also make the runtime zero-out the weak variable 
    date = nil; 

    NSLog(@"Date: %@", date); // prints (null) as expected 
    NSLog(@"Weak Date: %@", weakDate); // also prints (null) since it was weak and there were no more strong references to the original object 
} 
+0

只是一個問題,在第二個示例代碼中,您說:「這總是打印(空),因爲日期是__weak」,日期是零,但是有沒有內存泄漏?或者它已被釋放? – 2012-04-21 20:44:39

+0

@RamyAlZuhouri沒有內存泄漏。編譯器立即釋放新分配的日期,並且甚至不打擾分配(在這種情況下)。 – 2012-04-22 05:23:03

+0

NSLog(@「Weak Date:%@」,date);不應該是NSLog(@「Weak Date:%@」,weakDate); – NMunro 2013-07-18 19:16:47

3

關鍵錯誤在於將手動保持釋放行爲和ARC相提並論。事實並非如此。在ARC下,對象分配既是原子的,也是它們本身的決定對象生命週期的表達式。

舉一個例子,並刪除retain。你最終與此:

NSDate* date1=[[NSDate alloc]init]; 
NSDate* date2=date1; 
NSLog(@"%@",date2); 

在ARC下完美的感覺;沒有手動釋放的東西。即它會自動運行。

更好的是,因爲編譯器在後臺執行流控制分析,所以不需要額外的保留或釋放。該代碼將字面上是這樣的:

NSDate* date1; // date1 initialized to nil -- or not given that it is never read before... 
date1 = [[NSDate alloc]init]; // ... this assignment (of a +1 retain count obj) 
NSDate* date2=date1; // retain count unchanged 
NSLog(@"%@",date2); // retain count unchanged 
.... compiler emits equivalent to [date1 release] ... 

由於編譯器不會發出該release直到最後使用的date1date2後,永遠不會有一個懸擺指針。