Why isn’t my weak reference cleared right after the strong ones are gone?

objective-c, reference-counting, strong-references, weak-references

Solution

From the assembly code it can be seen that accessing `weakPtr` generates a `objc_loadWeak` call.

According to the Clang documentation, `objc_loadWeak` retains and autoreleases the object and is equivalent to

id objc_loadWeak(id *object) {
  return objc_autorelease(objc_loadWeakRetained(object));
}

This (hopefully) explains why both

if(strongPtr == weakPtr) ...

and

NSLog(@"weakPtr: %@", weakPtr);

create additional autoreleased references.

This is not a special `NSString` problem, I could reproduce the same behaviour with a custom (plain) class.

Problem

I am a little bit stubborn, but I want to understand weak and strong references well, so that's why I'm asking you once again. Consider this: ``` __weak NSString* mySecondPointer = myText; NSLog(@"myText: %@", myText); ``` The result is `myText: (null)` and it is pretty obvious - weak reference is set to null just after assignment, cause there is no strong reference to the pointed object. But in this case: ``` __strong NSString* strongPtr = [[NSString alloc] initWithFormat:@"mYTeSTteXt %d"]; // weak pointer points to the same object as strongPtr __weak NSString* weakPtr = strongPtr; if(strongPtr == weakPtr) NSLog(@"They are pointing to the same obj"); NSLog(@"StrongPtr: %@", strongPtr); NSLog(@"weakPtr: %@", weakPtr); NSLog(@"Setting myText to different obj or nil"); // after line below, there is no strong referecene to the created object: strongPtr = [[NSString alloc] initWithString:@"abc"]; // or myText=nil; if(strongPtr == weakPtr) NSLog(@"Are the same"); else NSLog(@"Are NOT the same"); NSLog(@"StrongPtr: %@", strongPtr); // Why weak pointer does not point to nul NSLog(@"weakPtr: %@", weakPtr); ``` The output: ``` 2013-03-07 09:20:24.141 XMLTest[20048:207] They are pointing to the same obj 2013-03-07 09:20:24.142 XMLTest[20048:207] StrongPtr: mYTeSTteXt 3 2013-03-07 09:20:24.142 XMLTest[20048:207] weakPtr: mYTeSTteXt 3 2013-03-07 09:20:24.143 XMLTest[20048:207] Setting myText to different obj or nil 2013-03-07 09:20:24.143 XMLTest[20048:207] Are NOT the same 2013-03-07 09:20:24.144 XMLTest[20048:207] StrongPtr: abc 2013-03-07 09:20:24.144 XMLTest[20048:207] weakPtr: mYTeSTteXt 3 // <== ?? ``` My question: Why after `strongPtr = [[NSString alloc] initWithString:@"abc"];` weak pointer value is not changed to nil (why the object created at the beginning still exists in memory, despite it does not have any strong refs? -- or maybe it has?) I have tried that one: (but it is not good for adding a comment I suppose). I have included the code where I am creating a strongPtr in @autorealesepool. I not sure if it is correct solution but it work... ``` __strong NSString* strongPtr; __weak NSString* weakPtr; @autoreleasepool { strongPtr = [[NSString alloc] initWithFormat:@"mYTeSTteXt %d", 3]; // weak pointer point to object create above (there is still strong ref to this obj) weakPtr = strongPtr; if(strongPtr == weakPtr) NSLog(@"They are pointing to the same obj"); NSLog(@"StrongPtr: %@", strongPtr); NSLog(@"weakPtr: %@", weakPtr); NSLog(@"Setting myText to different obj or nil"); // after line below, there is no strong referecene to the created object: strongPtr = [[NSString alloc] initWithString:@"abc"]; } if(strongPtr == weakPtr) NSLog(@"Are the same"); else NSLog(@"Are NOT the same"); NSLog(@"StrongPtr: %@", strongPtr); // Why weak pointer does not point to nul NSLog(@"weakPtr: %@", weakPtr); ``` Output: ``` 2013-03-07 09:58:14.601 XMLTest[20237:207] They are pointing to the same obj 2013-03-07 09:58:14.605 XMLTest[20237:207] StrongPtr: mYTeSTteXt 3 2013-03-07 09:58:14.605 XMLTest[20237:207] weakPtr: mYTeSTteXt 3 2013-03-07 09:58:14.606 XMLTest[20237:207] Setting myText to different obj or nil 2013-03-07 09:58:14.607 XMLTest[20237:207] Are NOT the same 2013-03-07 09:58:14.607 XMLTest[20237:207] StrongPtr: abc 2013-03-07 09:58:14.608 XMLTest[20237:207] weakPtr: (null) ```

Original source

Related problems