Обращение к слабому я внутри вложенного блока

Предположим, я уже создал слабую личность, используя

__weak typeof(self) weakSelf = self;
[self doABlockOperation:^{
        ...
}];

Внутри этого блока, если я вложу другой блок:

[weakSelf doAnotherBlockOperation:^{
    [weakSelf doSomething];
}

это создаст цикл сохранения? Нужно ли мне создавать еще одну слабую ссылку на weakSelf?

__weak typeof(self) weakerSelf = weakSelf;
[weakSelf doAnotherBlockOperation:^{
    [weakerSelf doSomething];
}

person Enzo Tran    schedule 14.06.2013    source источник


Ответы (2)


По-разному.

Вы создаете цикл сохранения только в том случае, если вы действительно сохраняете блок (поскольку self указывает на блок, а блок указывает на self). Если вы не собираетесь хранить ни один из блоков, достаточно использовать сильную ссылку на self --- блок будет освобожден первым после его выполнения, а затем он освободит указатель на self.

В вашем конкретном примере, если вы не выполняете больше операций, которые не показаны, вам не нужно создавать какие-либо weakerWeakerEvenWeakerSelfs.

person George Karpenkov    schedule 14.06.2013
comment
Итак, я понимаю, что часть о слабом «я» необходима, если, например, «я» сохраняет блок. Но какие операции я мог бы выполнять, что мне понадобится более слабое Я? - person Enzo Tran; 14.06.2013
comment
На самом деле, я думаю, вам никогда не понадобится weakerSelfs - слабый указатель помечен как не увеличивающий счетчик ссылок, и, следовательно, нет никакого способа сделать его слабее. - person George Karpenkov; 14.06.2013

Ваш код будет работать нормально: слабая ссылка не приведет к циклу сохранения, поскольку вы явно указываете ARC не увеличивать значение continueCount вашего слабого объекта. Однако для лучшей практики вы должны создать сильную ссылку на свой объект, используя слабую. Это также не создаст цикл сохранения, так как сильный указатель внутри блока будет существовать только до тех пор, пока блок не завершится (его единственная область - это сам блок).

__weak typeof(self) weakSelf = self;
[self doABlockOperation:^{
    __strong typeof(weakSelf) strongSelf = weakSelf;
    if (strongSelf) {
        ...
    }
}];
person Gianluca Tranchedone    schedule 14.06.2013
comment
Можете ли вы подробнее рассказать или дать мне несколько ссылок о том, почему я должен создать сильную ссылку на свой объект, используя слабую ссылку? 1 или 2 практических случая очень помогли бы. Спасибо. - person Enzo Tran; 14.06.2013
comment
Хорошая вещь в том, что вы можете безопасно проверить, существует ли объект, когда блок выполняется. В противном случае вы будете вызывать nil, что означает, что ваш блок мало что сделает. Советую посмотреть это видео с WWDC 2012 ;). - person Gianluca Tranchedone; 14.06.2013
comment
@EnzoTran: вы хотите создать сильную ссылку, потому что слабая ссылка безопасна только потому, что вы знаете, что self все еще будет действительным объектом к моменту выполнения блока. Но нет гарантии, что он не будет освобожден к моменту выполнения внутреннего блока, поэтому он должен захватывать сильную ссылку. - person newacct; 16.06.2013
comment
Я бы хотел, чтобы в Objective-C был какой-то синтаксис для абстрагирования этого стандартного шаблона. Я подумал что-то вроде __weak __strongcapture __typeof(self) weakSelf = self; Возможно, все слабые ссылки должны автоматически становиться сильными при доступе к ним внутри блока, хотя для обратной совместимости лучше было бы использовать __strongcapture. - person NathanAldenSr; 15.11.2013
comment
Вот сообщение в блоге, в котором есть еще одно хорошее объяснение этого шаблона: dhoerl.wordpress.com/2013/04/23/ - person smileyborg; 10.12.2013
comment
+1 для надежного указателя внутри блока будет существовать только до завершения блока - person onmyway133; 23.06.2014
comment
вам не нужно условие для strongSelf. Если вы не планируете делать что-то конкретное в случае, если это не nil, безопасно вызвать метод на nil - ничего не будет делать - person Julian; 19.10.2015