Удалить NSWindow из массива после закрытия
Я создаю окна программно, а затем добавляю их в массив, когда показываю их вот так.
NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:NO];
window.delegate = self;
window.releasedWhenClosed = YES;
[window makeKeyAndOrderFront:NSApp];
[_array addObject:window];
Мне нужно удалить окна из массива, когда они закрыты, но я не могу заставить это работать. Если я удаляю окно из моего массива в методе делегата -windowWillClose:
, как это, мое приложение аварийно завершает работу с EXC_BAD_ACCESS
после завершения метода делегата.
- (void)windowWillClose:(NSNotification *)notification
{
NSWindow *window = notification.object;
[_array removeObject:window];
}
3 ответа:
Задайте свойству окна
releasedWhenClosed
значение false, а не true.Установка этому свойству значения true, по существу, приводит к дополнительному освобождению, выходящему за рамки обычного управления памятью. Если вы используете ARC, то это один релиз слишком много, потому что сама ARC будет делать сбалансированные сохранения и релизы. (Если вы не используете ARC, то этот релиз будет уместен для балансировки
Во-вторых, перед удалением окна из массива задайте для свойства+alloc
в вашем первом фрагменте кода, который в противном случае не сбалансирован. Однако даже в этом случае я бы рекомендовал написание кода, который выполняет нормальное, сбалансированное управление памятью, и установка этому свойству значения false.)delegate
значениеnil
.Наконец, если это не исправит проблему, покажите детали аварии, включая трассировку стека.
Создание NSWindowController для NSWindow и хранение этих контроллеров в массиве (
NSMutableArray<NSWindowController *>
) вместо windows решает проблему.NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:NO]; window.delegate = self; NSWindowController *windowController = [[NSWindowController alloc] initWithWindow:window]; [windowController showWindow:self]; [_array addObject:windowController];
NSWindowDelegate
- (void)windowWillClose:(NSNotification *)notification { NSWindow *window = notification.object; [_array removeObject:window.windowController]; }