问题
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