Избегание "захвата себя в этом блоке, вероятно, приведет к появлению цикла сохранения"

каждый раз, когда мне приходится использовать глобальный 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 был освобожден.