Подтвердить что ты не робот

Возможно передать [self anyFunction] в блоках без объекта __weak (iOS 5 + ARC)

Можно ли передать [self anyFunction] в блоках без объекта __weak из self?

В качестве примера это допустимый код из System Framework:

[UIView animateWithDuration:0.8 animations:^{
            //Do animationStuff
        } completion:^(BOOL finished) {
            [self anyFunction];
 }];

Вы можете передать [self anyFunction] в блок завершения без предупреждения. Но если вы напишете свой собственный метод с блоком завершения, появляется следующее предупреждение: фиксировать "я" сильно в этом блоке, вероятно, приведет к циклу сохранения.

Рабочее решение довольно просто (iOS 5 + ARC). Перед объявлением блока:

__weak MyClass *weakSelf = self;

а в блоке завершения вы должны позвонить:

[weakSelf anyFunction];

Но вернемся к моему вопросу: почему нет необходимости в API-интерфейсах System Framework использовать объект __weak и использовать self без каких-либо предупреждений. И как реализовать метод без необходимости объекта __weak в блоке?

Спасибо за ваши усилия.

4b9b3361

Ответ 1

Блоки, которые вызывают ошибку, являются теми, где вы захватываете объекты, которые владеют блоком. Например

[object performBlock:^{
    [object performSomeAction]; // Will raise a warning
}];

или

[self performBlock:^{
    [self doSomething];    // Will raise a warning
}];

но

[self performBlock:^{
    [object doSomething];    // <-- No problem here
}];   

Поскольку объект сохраняет свои блоки, а блок сохраняет его. Таким образом, в обоих случаях объект, который выполняет блок, владеет блоком, который также владеет объектом. Таким образом, у вас есть цикл - цикл сохранения. что означает утечку памяти.

В примере, который вы указали, вы смотрите на метод класса . Вы вызываете блок в классе UIView, а не в объекте UIView. У класса нет памяти, связанной с ним. И вы, вероятно, вызываете эту функцию из контроллера, поэтому ссылка self сохраняется блоком, но цикла нет, потому что self не сохраняет блок.

Таким же образом, возможно, вы заметили, что не все объекты, которые используются в блоке, должны быть слабо указаны - только те, которые вызывают цикл сохранения.

Ответ 2

В коде, который мне нужно компилировать потенциально с ARC или без него, или с новыми компиляторами или без них, я делаю следующее... функционально это то же самое, что и вы уже перечислили, но он избегает the__weak, а также избегает циклы удерживания:

//
// FOR NON-ARC PROJECTS
//
__block __typeof__(self) bself = self;
[someObject doThingWithBlock:^(id result){
    if (!bself)
        return;
    bself.thingWhich = result;
}];

///
// FOR ARC PROJECTS
//
__weak MyClass *bself = self;
[someObject doThingWithBlock:^(id result){
    if (!bself) 
        return;
    bself.thingWhich = result;
}];