我何时以及为什么要使用ARC将局部变量声明为__weak?

时间:2012-01-10 15:54:07

标签: ios iphone xcode automatic-ref-counting weak-references

Mike Ash has written this introduction to ARC他介绍了类似的内容:

__weak Foo *_weakFoo = [object foo];

为什么我要为本地临时变量执行此操作? __weak是一个归零引用,只要引用的对象被释放,它就会自动将_weakFoo指针设置为nil。此外,__ weak仅适用于iOS> = 5。

当我这么做时,我什么时候会遇到麻烦?:

Foo *_weakFoo = [object foo];

总是希望返回一个对象或零。我猜是这样的:

Foo *_weakFoo = [object foo];
[self doSomethingStupid]; // does something bad so foo gets deallocated
[_weakFoo doIt]; // CRASH! msg sent to deallocated instance 0x123456

仍然让我厌烦ARC的一件事是:它何时知道我不再需要一个物体了?我认为当我设置一个指向nil或其他东西的指针时,它会发现此所有者不再需要先前引用的对象,因此可能会消失。但问题是:我把它设置为零。所以它无论如何都是零!

那么什么时候__weak的局部变量才有意义,我必须在其他地方做什么样的疯狂才能真正需要呢?

1 个答案:

答案 0 :(得分:9)

如果我必须操作块内的__weak以避免保留周期,我会使用self局部变量。考虑这个例子我正在使用GCD和块来执行字符串的网络请求,然后在类声明的标签上设置它,在本例中为TurtlesViewController

__weak TurtlesViewController *weakSelf = self;
dispatch_queue_t networkQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(networkQueue, ^{

    // Kick off a network task for some data that is going to populate a label declared on our class
    NSString *returnString = [networkDataSource retrieveTurtleTime];

    // Dispatch back to the main thread to populate the UILabel
    dispatch_async(dispatch_get_main_queue(), ^{

        // Using self.label here creates a retain cycle. Self owns the block and the block has captured self
        self.label.text = returnString;

        // Instead, we use weakSelf for our reference to the label as it will be torn down by ARC at the end of the loop.
        weakSelf.label.text = returnString;
    });
});