Objective-C: Weak attritube don't work as expected [duplicate]

牧云@^-^@ 提交于 2019-12-09 15:14:00

问题


Possible Duplicate:
Why do weak NSString properties not get released in iOS?

I'm a newbie to Objective C and I've got some questions that I cannot answer myself. I have a block of code for testing __weak variable (I'm using ARC, of course):

NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
myString = nil; //<-- release the NSString object
NSLog(@"string: %@", weakString);

The output of the above codes is as expected, since weakString is a weak variable :

2013-01-02 11:42:27.481 ConsoleApp[836:303] string: (null)

But when I modified the code to this:

NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
NSLog(@"Before: %@", weakString); //<--- output to see if the __weak variable really works.
myString = nil;
NSLog(@"After: %@", weakString);

The output is totally not what I expected:

2013-01-02 11:46:03.790 ConsoleApp[863:303] Before: John
2013-01-02 11:46:03.792 ConsoleApp[863:303] After: John

The output of the latter NSLog must have been (nil) instead of "John". I've tried to search in many documents but I haven't found the answer for this case. Can someone give an reasonable explaination? Thanks in advance.


回答1:


The NSLog function is retaining the passed NSString in an autorelease pool. The zeroing-weak variable will therefore not be zeroed until the autorelease pool has drained. For example:

__weak NSString* weakString = nil;

@autoreleasepool {
    NSString* myString = [[NSString alloc] initWithFormat:@"Foo"]; // Retain count 1
    weakString = myString;         // Retain count 1
    NSLog(@"A: %@", weakString);   // Retain count 2
    NSLog(@"B: %@", weakString);   // Retain count 3
    myString = nil;                // Retain count 2
    NSLog(@"C: %@", weakString);   // Retain count 3

    NSAssert(weakString != nil, @"weakString is kept alive by the autorelease pool");
} 

// retain count 0
NSAssert(weakString == nil, @"Autorelease pool has drained.");

Why is NSLog putting the string into an autorelease pool? That's an implementation detail.

You can use the debugger or Instruments to follow the retain count of the NSString instance. The exact retain counts are unimportant, but it does shed some light as to what's going on behind the scenes. What is important is that the NSString instance is deallocated when the autorelease pool is drained.




回答2:


I think it’s just some implementation detail. Your weak variable is getting cleared, but not just immediately. For example, this works as expected:

NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
@autoreleasepool {
    NSLog(@"Before: %@", weakString);
    myString = nil;
}
NSLog(@"After: %@", weakString); // nil


来源:https://stackoverflow.com/questions/14116993/objective-c-weak-attritube-dont-work-as-expected

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