Сильная ссылка на слабые ссылки внутри блоков

Почему необходимо иметь сильную ссылку на слабую ссылку внутри блока?

Я понимаю, что наличие слабой ссылки внутри блока позволит избежать циклов сохранения. Но почему снова должна быть сильная ссылка на слабого?

Фон:
Как сказал Мейсон, это лучшая практика.

Я знаю, что правильный способ сослаться на себя внутри блока - создать слабую ссылку вне блока, а затем сильную ссылку на эту слабую ссылку внутри блока [...]

Пример:

__weak typeof(self) weakSelf = self;
void (^someBlock)(id) = ^(id data){
    typeof(self) strongSelf = weakSelf;
    // code using strongSelf
});

2 ответа

Решение

Представьте, что последняя остающаяся сильная ссылка на себя хранится в потоке, отличном от того, в котором работает ваш блок.

Теперь это происходит:

__weak typeof(self) weakSelf = self;
void (^someBlock)(id) = ^(id data){
    if (weakSelf != nil) {
       // last remaining strong reference released by another thread. 
       // weakSelf is now set to nil.
       [myArray addObject:weakSelf];
    }
});

Это приведет к сбою с исключением NSInvalidArgument для добавления nil в массив.

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

Если вы на 100% уверены, что на объект будет ссылаться только один поток, делать это не обязательно. Но делать такое предположение - плохая практика.

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

Другие вопросы по тегам