2015-10-20 3 views
3

Я создаю окна программно, а затем добавляю их в массив, когда я показываю их так.Удалить 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]; 
} 
+0

Show. Ваш. Код. Благодаря! – matt

+1

Также: вы действительно думаете, что разумно хранить сильную ссылку на главный объект, такой как NSWindow, который не принадлежит вам? Зачем вам это нужно? Приложение знает, какие окна есть; для чего этот массив? – matt

+0

Хорошо, я добавил код. Если я не сохраню сильную ссылку, окно не будет отображаться. Кроме того, в зависимости от действия пользователя он будет отображать существующее окно вместо создания нового. –

ответ

1

Создание NSWindowController для NSWindow и сохранение этих контроллеров в массиве (NSMutableArray<NSWindowController *>) вместо окон решает проблему.

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]; 
} 
+0

Отлично! Думаю, я контролирую ваш код, что вы храните 'NSWindow'. Я всегда думал, что вы храните 'NSWindowController', и это то, о чем я говорил в своем ответе. – Abhinav

+1

Обратите внимание, что 'releaseWhenClosed' игнорируется для окна, которое управляется оконным контроллером. Нет смысла настраивать его. –

+0

Спасибо за подсказку! Я удалил эту строку. –

0

Я считаю, что контроллер окно будет освобождаться по АРК в середине windowWillClose:. Вместо этого попробуйте с windowShouldClose:.

+0

Он по-прежнему падает с использованием этого метода. –

+0

Я вижу. Я думаю, вы можете захотеть следовать [этой теме] (http://www.cocoabuilder.com/archive/cocoa/116358-releasing-nswindowcontroller-when-the-window-closes.html) для другой альтернативы. – Abhinav

3

Установите для свойства releasedWhenClosed окна значение false, а не true.

Установка этого свойства в истинное значение, по сути, приводит к дополнительному выпуску, превышающему нормальное управление памятью. Если вы используете ARC, то это один выпуск слишком много, потому что сам ARC будет делать сбалансированные сохранения и релизы. (Если вы не использовали ARC, тогда этот выпуск был бы подходящим для баланса +alloc в вашем первом фрагменте кода, который в остальном не сбалансирован. Однако даже в этом случае я бы рекомендовал написать код, который будет работать нормально, сбалансированно управлять памятью и установив для этого свойства значение false.)

Во-вторых, установите свойство delegate окна nil, прежде чем удалять его из массива.

И наконец, если это не устраняет проблему, покажите детали сбоя, включая трассировку стека.

+0

Спасибо за идею! Это все еще вызвало крах, но я нашел решение. –

Смежные вопросы