Я использую блоки для обработки ответа асинхронных http-запросов в не-ARC-проекте. Код выглядит так (соответствующие части):
NSMutableUrlRequest* request = ...;
__block typeof(self) mutableSelf = self;
void (^didGetSessionBlock)(Gopher* newGopher) = ^(Gopher* newGopher) {
if (newGopher.statusCode == HTTP_OK) {
...
mutableSelf.retryOnFail = NO;
[mutableSelf executeRequest:request];
}
...
[mutableSelf setStatusCode:newGopher.statusCode];
};
Gopher* newGopher = [[[Gopher alloc] init] autorelease];
[newGopher setDidCompleteBlock:didGetSessionBlock];
[newGopher fetchSession:myApp.settings.userName password:myApp.settings.password];
__block mutableSelf
используется для того, чтобы я мог изменить self
внутри блока (а не копию self
). Ключевое слово __block
, если я правильно понимаю, также приводит к тому, что mutableSelf
не сохраняется, поэтому он может быть уже освобожден во время выполнения блока (и это именно то, что происходит).
Если я изменюсь
[mutableSelf executeRequest:request];
до
[self executeRequest:request];
все хорошо, поскольку self
сохраняется и не будет выпущен, пока блок не будет выполнен. Однако прямая ссылка на себя может привести к утечкам из-за циклов сохранения.
Есть ли способ обойти это? Должен ли я вручную сохранить mutableSelf
, когда он объявлен, и затем освободить его внутри блока? Или я должен использовать self
внутри блока, где я не изменяю его, потенциально создавая утечку? Оба варианта кажутся хрупкими и нуждаются в пояснениях в комментариях, чтобы избежать путаницы и будущих ошибок, если / когда код будет изменен.
Есть ли способ решить эту проблему? Если нет, то какой подход лучше?