#iphone #objective-c #cocoa #nsfilecoordinator
#iPhone #objective-c #какао #nsfilecoordinator
Вопрос:
Это один тривиальный вопрос управления памятью, связанный с блоками, и я не уверен, когда / где fc
следует выпустить
NSFileCoordinator *fc = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
NSError *error = nil;
[fc coordinateWritingItemAtURL:sourceURL
options:NSFileCoordinatorWritingForDeleting
error:amp;error
byAccessor:^(NSURL *newURL) {
// if error is not nil this block will not be called
NSError *anError = nil;
NSFileManager *fm = [NSFileManager defaultManager];
[fm removeItemAtURL:newURL error:amp;anError];
dispatch_async(q_main, ^{
// change to the main queue and update the UI
completion(anError);
});
// *** (1) Release here ? ***
// [fc release];
}];
// *** (2) or Release here ? ***
// [fc release]
if (error) {
// change to the main queue and update the UI
dispatch_async(q_main, ^{
completion(error);
});
}
Я думаю, что выпуск в (1) был бы в порядке (без утечек), но действительно ли это стандартный способ ведения дел? (освобождение объекта в блоке, который вызывает тот же объект ??). Я чувствую здесь некоторую странность.
В (2) тоже нормально, но только потому, что блок доступа вызывается синхронно.
В учебных целях… что, если этот блок доступа будет вызываться асинхронно? (Воображаемый случай, не необходимый для NSFileCoordinator) В таком случае мне нужно было бы создать fc
ivar или это просто нормально для первого подхода?
Любая помощь приветствуется
🙂
Комментарии:
1. Это противоречивый ответ, но поскольку вы используете 10.7, почему бы не использовать ARC?
2. Я тоже так думал, но мне просто не нравится идея перехода на ARC без знания этих деталей 🙂
Ответ №1:
Для данного кода я бы выпустил в (2). Если вы отпустите at (1), вы можете снести fc
из-под себя. Нет способа узнать, что fc
может потребоваться сделать после вызова блока.
Для асинхронного случая я использовал подобный код (хотя и не с NSFileCoordinator
):
__block NSWindowController *wc = [[NSWindowController alloc] initWithWindowNibName:@"foo"];
[NSApp beginSheet:[wc window] modalForWindow:[self window] completionHandler:^(NSInteger returnCode) {
if(NSOKButton == returnCode) {
// Do something
}
[wc release], wc = nil;
}];
-beginSheet:modalForWindow:completionHandler:
это категория, в которую я добавил NSApplication
.
Комментарии:
1. Я думаю, что (2) — лучшее место 🙂 . Также вы сказали, что не выпустили бы его в (1), потому что мы не знаем, что
fc
происходит после блокировки, но в предполагаемом случае мы бы это сделали, и это было бы самое последнее, что он делает, было бы нормально выпустить его там?2. Да, я думаю, если бы вы знали, что самое последнее, что делается
fc
, — это вызвать ваш блок, тогда освобождение в (1) или (2) было бы эквивалентно3. Я думаю, что в ARC внутри блока генерируется неявное
retain
, поэтому все, что ему нужно, доступно, даже если вызывающий абонент давно ушел и выпустил все. Я полагаю, что без ARC, возможно, было бы неплохо сделать то же самое, и вы выпустили оба места, но добавили еще одно сохранение где-нибудь? Имеет ли это какой-либо смысл?