2012-01-10 72 views
5

Mike Ash has written this introduction to ARC他介绍是这样的:何时以及为什么要使用ARC将局部变量声明为__weak?

__weak Foo *_weakFoo = [object foo]; 

我为什么要那样做的地方,临时变量? __weak是一个归零参考,一旦被引用的对象被释放,_weakFoo指针就会自动设置为零。此外,__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是什么时候知道我不再需要一个对象?我会争辩说,当我设置一个指向零或其他东西的指针时,它会发现先前引用的对象不再需要这个所有者,因此可能会消失。但重点是:我把它设置为零。所以它无论如何都是零!

那么什么时候__弱化一个局部变量是有意义的,以及什么样的疯狂的事情,我必须在别的地方做,这样我真的需要吗?

回答

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; 
    }); 
}); 
+1

虽然怎么会有保留周期? – openfrog 2012-01-10 16:24:51

+1

@openfrog - 这个特定块可能不会成为保留周期的最大风险,但我遇到的一个块是基于块的通知观察者(使用NSNotificationCenter的“-addObserverForName:object:queue:usingBlock:' )。如果你在一个对象中设置了这样一个观察者,并且在'self'上引用了某个东西,那么随着对象保持在该块上并且该块保持在该对象上,您将设置一个循环。 – 2012-01-10 21:17:50

+2

写完这个之后,我意识到这不是最好的例子,因为dispatch_async()复制了这个块,但是直到这个方法结束。一个更好的例子会一直使用NSBlockOperation,因为这样的实例拥有对象生命周期中的块传递,使保留周期更有可能。 – 2012-01-11 01:07:34

相关问题