4

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?

Nelu
  • 16,644
  • 10
  • 80
  • 88

2 Answers2

1

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.

Caleb
  • 124,013
  • 19
  • 183
  • 272
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.");
}
Lei
  • 318
  • 1
  • 6