Сохранение изменяемых переменных в блоках без сохранения циклов в Objective-C - PullRequest
2 голосов
/ 20 марта 2012

Я использую блоки для обработки ответа асинхронных 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 внутри блока, где я не изменяю его, потенциально создавая утечку? Оба варианта кажутся хрупкими и нуждаются в пояснениях в комментариях, чтобы избежать путаницы и будущих ошибок, если / когда код будет изменен.

Есть ли способ решить эту проблему? Если нет, то какой подход лучше?

1 Ответ

3 голосов
/ 20 марта 2012

Вы не модифицируете self в блоке, вы изменяете только объект, на который он указывает. Я не думаю, что вам нужно __block.

...