#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]
внутри блока, и все будет работать правильно. Что произойдет, если вы это сделаете?