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