#objective-c #block #retain-cycle
#objective-c #блок #сохранение цикла
Вопрос:
Мне нужно выполнить один и тот же набор кода в двух блоках (я использую ARC):
__weak typeof(self) weakSelf = self;
[_dataProvider doA:^(NSError *error) {
[weakSelf handleError:error];
}];
И в другом месте я вызываю:
__weak typeof(self) weakSelf = self;
[_dataProvider doB:^(NSError *error) {
[weakSelf handleError:error];
}];
Тогда у меня есть мой обработчик:
- (void)handleError:(NSError *)error {
[self.refreshControl endRefreshing];
[self.tableView reloadData];
}
Это сохранить, чтобы использовать его таким образом? Пожалуйста, обратите внимание, что handleError:
метод использует self
inside. Если нет, то каков здесь правильный подход? КСТАТИ: self является ViewController и может быть освобожден (doB: и doA: блоки основаны на сети, поэтому могут быть медленными).
Комментарии:
1. что вы имеете в виду, безопасно ли это использовать ? это не взорвет ваше устройство … так что, да, это безопасно с этой точки зрения.
2. это не «полностью» безопасно, см. Мой ответ.
Ответ №1:
Это небезопасно делать, даже если многие люди делают это так.
Вы должны использовать шаблон «weakSelf» с блоками, когда это оправдано. В вашем примере шаблон «weakSelf» не оправдан, потому self
что не имеет никакой strong
ссылки на ваш block
. Вы можете использовать так :
[_dataProvider doA:^(NSError *error) {
// here you can use self, because you don't have any strong reference to your block
[weakSelf handleError:error];
}];
Используйте шаблон «weakSelf», если у вас есть strong
ссылка на ваш block
(например, со свойством или переменной экземпляра), и вы записываете self
внутри block
, например :
@property(strong) void(^)(void) completionBlock;
....
__weak typeof(self) weakSelf = self;
self.completionBlock = ^{
// Don't use "self" here, it will be captured by the block and a retain cycle will be created
// But if we use "weakSelf" here many times, it risques that it will be nil at the end of the block
// You should create an othere strong reference to the "weakSelf"
__strong typeof(self) strongSelf = weakSelf;
// here you use strongSelf ( and not "weakSelf" and especially not "self")
};
Комментарии:
1. Я слышал что-то подобное. Однако xCode не согласен с этим, насколько я понимаю —
[_someInstance doC:^(NSError *error) { self.index = 5; }];
(где@property (nonatomic, assign) NSInteger index;
). Претензии XCodeCapturing 'self' strongly in this block is likely to lead to a retain cycle
. У меня нет ни свойства, ни ivar для этого блока, почему я получаю предупреждение?2. Я отключу предупреждение, выполнив: #pragma clang diagnostic push #pragma clang diagnostic игнорируется «-Warc-retain-cycles» …. ваш блок здесь #pragma clang diagnostic pop
3. Итак, вы утверждаете, что это общее предупреждение, и я не должен заботиться об этом в данном конкретном случае? Я обычно нахожу предупреждения полезными, и я боюсь, что за предупреждением скрывается какая-то «правда». Однако, если вы уверены, что в этом случае все в порядке, тогда я понимаю, как это работает.