2012-04-19 126 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后,永远不会有一个悬摆指针。