Когда и почему я хотел бы объявить локальную переменную как __weak, используя ARC? - PullRequest
5 голосов
/ 10 января 2012

Майк Эш написал это введение в ARC , где он вводит что-то вроде:

__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, такова: когда он узнает, что мне больше не нужен объект?Я бы сказал, что когда я устанавливаю указатель на nil или что-то еще, он обнаруживает, что ранее указанный объект больше не нужен этому владельцу и, следовательно, может уйти.Но дело в том, что я установил его на ноль.Так что в любом случае это ноль!

Так, когда бы __weak для локальной переменной имел смысл, и какие сумасшедшие вещи я должен делать где-то еще, чтобы мне это действительно нужно?

1 Ответ

9 голосов
/ 10 января 2012

Я использую __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;
    });
});
...