ObjectiveC: weird behavior when using NSString and __weak with ARC

First code and output:

NSString *text = @"Sunny"; __weak NSString *string0 = text.lowercaseString; __weak NSString *string1; string1 = text.lowercaseString; NSLog(@"%@, %@", string0, string1); 

Output:

 (null), sunny 

But after moving the string1 declaration above text output is different. Here is the code:

 __weak NSString *string1; NSString *text = @"Sunny"; __weak NSString *string0 = text.lowercaseString; string1 = text.lowercaseString; NSLog(@"%@, %@", string0, string1); 

Output:

 sunny, sunny 

I am very confused with different output:

  • Why are string0 and string1 different in the first case?
  • Why is the output of the second register different from the first?
+6
source share
1 answer

Trying to find out exactly when the object will be released or a weak task will challenge, and often does not help to understand. Here are a few reasons why you can see different results than you expect:

  • NSString : It's best never to use this type when doing this kind of research. String literals are immortal, they are not collected, and you may have a string literal, even if you do not expect it.
  • Auto-release pool: The auto-release pool is really a hangover from days to ARC, but it still exists, and many methods return automatically issued objects. This means that many objects will live longer than you might expect, but not for too long. However, ARC has tricks and can remove objects from the auto-release pool earlier, so you might first think that the object will live longer, and then it won't ...
  • weak links: after the first two bullets, you should guess that, since you may not have a real idea when an object will be released, if at all, then you may not have a real idea when a weak link becomes zero. Just think "soon enough."
  • Optimization. There is some freedom in optimization that the compiler can do, which, while maintaining the correct semantics of your program, can change the lifetime of objects.

If you want to run such research, you will probably get even more if (a) use your own class types and not something from the libraries, and (b) use @autoreleasepool { ... } blocks to limit lifespan auto-released objects.

As an example, when I ran your code in the compiler that I used, I did not get (null) , however, changing the first assignment to string0 = text.lowercaseString.mutableCopy really caused one ... Finding out the reasons left as an exercise ...

Have a questioning mind and explore, it’s good, but be prepared for the non-obvious!

NTN

+6
source

All Articles