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

ope*_*rog 5 iphone xcode weak-references ios automatic-ref-counting

Mike Ash已将此介绍写入ARC,他在此介绍了以下内容:

__weak Foo *_weakFoo = [object foo];
Run Code Online (Sandbox Code Playgroud)

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

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

Foo *_weakFoo = [object foo];
Run Code Online (Sandbox Code Playgroud)

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

Foo *_weakFoo = [object foo];
[self doSomethingStupid]; // does something bad so foo gets deallocated
[_weakFoo doIt]; // CRASH! msg sent to deallocated instance 0x123456
Run Code Online (Sandbox Code Playgroud)

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

所以,当局部变量的__weak有意义时,我必须在其他地方做什么样的疯狂事情,以便我真的需要它?

Mar*_*ams 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;
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 写完之后我意识到这不是最好的例子,因为dispatch_async()复制了块,但只是直到方法结束.一个更好的例子就是使用NSBlockOperation,因为这样的实例在对象的生命周期内拥有传入的块,从而更有可能使保留周期成为可能. (2认同)