Возможно передать [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 объект в блоке?

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

2 ответа

Решение

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

[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 не сохраняет блок.

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

В коде, который мне нужно скомпилировать потенциально или без ARC, или с новыми компиляторами или без них, я делаю следующее... функционально это то же самое, что вы уже перечислили, но избегает __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;
}];
Другие вопросы по тегам