在Objective-C中,弱引用何时更新为nil?

时间:2013-08-05 21:32:28

标签: objective-c pointers automatic-ref-counting weak-references

考虑以下两种情况:

// case 1
NSObject *strongOne = [[NSObject alloc] init];
NSObject * __weak weakOne = strongOne;

if (weakOne) {
    NSLog(@"weakOne is not nil.");
} else {
    NSLog(@"weakOne is nil.");
}

strongOne = nil;

if (weakOne) {
    NSLog(@"weakOne is not nil.");
} else {
    NSLog(@"weakOne is nil.");
}

输出:

weakOne is not nil.
weakOne is not nil.

// case 2
NSObject *strongOne = [[NSObject alloc] init];
NSObject * __weak weakOne = strongOne;

strongOne = nil;

if (weakOne) {
    NSLog(@"weakOne is not nil.");
} else {
    NSLog(@"weakOne is nil.");
}

输出:

weakOne is nil.

据我所知,当strongOne被解除分配时,对同一对象的弱引用应更新为nil

我的问题:为什么这只发生在case 2

2 个答案:

答案 0 :(得分:1)

  

据我所知,当strongOne被解除分配时,弱引用   同一个对象应该更新为nil。

没错。但是当你将strongOne设置为nil时,你不会解除对象的释放,你只是在改变指针。 ARC可能会在对象autorelease上调用strongOne指向,因此直到稍后自动释放池耗尽时才会释放该对象。

  

为什么这只发生在案例2中?

在这种情况下,ARC似乎发送release,因此对象将被释放,您的弱引用会立即更新。

或者,可能是编译器注意到在将其设置为nil之前从不使用strongOne,除非将其分配给弱指针,因此决定不首先分配对象。逐步执行该代码,看看strongOne是否获得非零值。

答案 1 :(得分:1)

我认为这是因为当你使用weakOne进入if语句时会增加自动释放池中的保留计数;因此,在自动释放池耗尽之前,弱指针不会为零。

 // Try this
NSObject *strongOne = [[NSObject alloc] init];
NSObject * __weak weakOne = strongOne; //count 1
@autoreleasepool {

    if (weakOne) { 
        NSLog(@"weakOne is not nil."); //count 2
    } else {
        NSLog(@"weakOne is nil.");
    }

    strongOne = nil; // count 1

    if (weakOne) { 
        NSLog(@"weakOne is not nil.");
    } else {
        NSLog(@"weakOne is nil.");
    }

} // count 0, therefore the weakOne become nil

if (weakOne) {
    NSLog(@"weakOne is not nil.");
} else {
    NSLog(@"weakOne is nil.");
}