这个问题已经在这里有了答案:
已关闭8年。
我是Objective C的新手,我有一些自己无法回答的问题。
我有一段代码用于测试__weak变量(当然,我使用的是ARC):
NSString *myString = [[NSString alloc] initWithFormat:@"John"];
NSString * __weak weakString = myString;
myString = nil; //<-- release the NSString object
NSLog(@"string: %@", weakString);
上面的代码的输出与预期的一样,因为weakString是一个弱变量:
2013-01-02 11:42:27.481 ConsoleApp[836:303] string: (null)
但是,当我修改代码到此:
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);
输出完全不是我期望的:
2013-01-02 11:46:03.790 ConsoleApp[863:303] Before: John
2013-01-02 11:46:03.792 ConsoleApp[863:303] After: John
后一个NSLog的输出必须为(nil),而不是“John”。我尝试搜索许多文档,但没有找到这种情况的答案。
有人可以给出合理的解释吗?提前致谢。
最佳答案
NSLog
函数将传递的NSString保留在自动释放池中。因此,在自动释放池耗尽之前,不会将零清零变量清零。例如:
__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.");
为什么NSLog将该字符串放入自动释放池中?这是一个实现细节。
您可以使用调试器或乐器来跟踪NSString实例的保留计数。确切的保留计数并不重要,但是它确实揭示了幕后发生的事情。重要的是,耗尽自动释放池后,将释放NSString实例。
关于ios - Objective-C : Weak attritube don't work as expected,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14116993/