Возможно передать [self anyFunction] в блоках без __weak объекта (iOS 5 + ARC) - PullRequest
23 голосов
/ 25 января 2012

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

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

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

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

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

__weak MyClass *weakSelf = self;

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

[weakSelf anyFunction];

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

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

Ответы [ 2 ]

53 голосов
/ 25 января 2012

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

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

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

14 голосов
/ 24 февраля 2012

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

//
// 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;
}];
...