When does a weak reference get updated to nil in Objective-C? [duplicate]

浪尽此生 提交于 2019-11-30 17:45:50

问题


Consider the following two cases:

// 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.");
}

Outputs this:

weakOne is not nil.
weakOne is not nil.

And

// 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.");
}

Outputs this:

weakOne is nil.

As far as I know, when strongOne is deallocated, the weak reference to the same object should be updated to nil.

My question: Why does that only happen in case 2?


回答1:


I think this is because when you get into the if statement with weakOne will increment the retain count in autorelease pool; therefore, the weak pointer will not be zero until the autorelease pool drained.

 // 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.");
}



回答2:


As far as I know, when strongOne is deallocated, the weak reference to the same object should be updated to nil.

That's right. But you're not deallocating the object when you set strongOne to nil, you're just changing the pointer. ARC probably calls autorelease on the object strongOne points to, so the object won't actually be deallocated until later, when the autorelease pool is drained.

Why does that only happen in case 2?

Looks like ARC sends release in that case, so the object is deallocated and your weak reference is updated right away.

Or, it might be that the compiler notices that you never use strongOne before setting it to nil, except to assign it to a weak pointer, and so decides not to allocate the object in the first place. Step through that code and see if strongOne ever gets a non-nil value.



来源:https://stackoverflow.com/questions/18068119/when-does-a-weak-reference-get-updated-to-nil-in-objective-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!