Как освободить объект при использовании блочного обратного вызова

#iphone #objective-c #memory-leaks #callback #objective-c-blocks

#iPhone #objective-c #утечки памяти #обратный вызов #objective-c-блоки

Вопрос:

вероятно, это вопрос новичка, касающийся управления памятью.

Как я могу освободить объект при использовании блоков в качестве обратного вызова в objective c?

(Обновленный код)

 @implementation ObjectWithCallback
- (void)dealloc {
    [_completionHandler release];
    [super dealloc];
}
- (void)doTaskWithCompletionHandler:(void(^)(void))handler {
    _completionHandler = [handler copy];
    // Start tasks...
}
- (void)tasksDone {
    // Do callback block
    _completionHandler();
    // Delete reference to block
    [_completionHandler release];
    _completionHandler = nil;
}

// Use of the ObjectWithCallback
ObjectWithCallback *request = [[ObjectWithCallback alloc] init];
[request doTaskWithCompletionHandler:^(void){
    // Callback called and task is ready.
}];
  

Комментарии:

1. Какой объект вы хотите освободить, и почему вы не можете освободить его внутри блока?

2. Что заставляет вас думать, что вы не можете повторно использовать объект в блоке?

3. Он хочет освободить request .

Ответ №1:

Быстрый, неполный ответ: [request autorelease]

Проблема с этим заключается в том, что блоки неявно сохраняют любые объекты, на которые ссылаются внутри тела блока. Таким образом, блок сохраняется request и request сохраняет блок, что приводит к циклу сохранения, и никто не освобождается.

Чтобы исправить это, вы объявляете свою request переменную как __block , что не позволяет блоку сохранять захваченный объект:

 __block ObjectWithCallback *request = [[ObjectWithCallback alloc] init];
  

Рекомендуемое чтение:

Комментарии:

1. __block не следует использовать в этом центре сертификации. Срок службы объекта явно привязан к блоку, и сохранение блока гарантирует это.

2. @bbum Я думаю, что понимаю, что вы имеете в виду, но не приведет ли это к циклу сохранения, если блок ссылается request ? Я предполагаю, что обходным путем было бы ObjectWithCallback освободить блок обратного вызова после его вызова.

3. Ах — да — другая проблема, ортогональная вопросу OP. Сумасшедший.

4. Спасибо за ответы, я изучу ваши советы по чтению. Похоже, что это может быть цикл сохранения. Я думал, что освободил ссылку на блок из объекта, но, похоже, это не работает (код обновлен)

5. Глядя на ваш обновленный код, поскольку вы освобождаете блок после его вызова, вы должны быть в состоянии просто выполнить [request release] внутри блока, и все будет работать правильно. Что произойдет, если вы это сделаете?