Избегание "захвата себя в этом блоке, вероятно, приведет к появлению цикла сохранения"
каждый раз, когда мне приходится использовать глобальный var или свойство внутри блока следующим образом:
self.save = ^(){
if (isItSaving == NO) {
[self saveMyFile];
}
};
Мне нужно переписать это как
BOOL *iis = isItSaving;
id myself = self;
self.save = ^(){
if (iis == NO) {
[myself saveMyFile];
}
};
или Xcode будет жаловаться: "захват себя сильно в этом блоке, вероятно, приведет к циклу сохранения...
Он жалуется даже на переменные BOOL?
Обновление всех элементов перед тем, как блок станет хромым решением.
Правильно ли это? Есть ли элегантный способ?
Этот материал уродлив. Я использую ARC.
Ответы
Ответ 1
Проблема возникает только при указании self
внутри блока, явно или неявно. При доступе к глобальным переменным не появляется предупреждение.
В вашем случае вы, вероятно, обратились к булевому ivar. Доступ к ivar неявно использует self
, поэтому компилятор предупреждает вас (правильно) о цикле сохранения.
Общий способ исправить цикл сохранения:
typeof(self) __weak weakSelf = self;
self.save = ^() {
typeof(weakSelf) __strong strongSelf = weakSelf;
if (strongSelf != nil && ! strongSelf->isItSaving) {
[strongSelf saveMyFile];
}
};
... и, да, это немного уродливая часть блоков.
Ответ 2
Используйте __unsafe_unretained typeof(self) weakSelf = self;
Ответ 3
В дополнение к ответу @NikolaiRuhe в вашем примере при объявлении свойств
BOOL *iis = isItSaving;
id myself = self;
подразумевает ссылки strong
, поэтому используйте __weak
self, чтобы предотвратить цикл сохранения. Тогда вы можете задаться вопросом, почему вам нужно объявить ссылку __strong
для слабого "я" внутри блока, и чтобы убедиться, что она не освобождается в течение срока действия блока, иначе weakSelf->isItSaving
сломается, если self
был освобожден.