这个问题已经在这里有了答案:




已关闭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/

10-12 14:36
查看更多