Немодальное управление памятью Windows - PullRequest
2 голосов
/ 20 декабря 2009

Я новичок в Mac Dev. Я пришел с iPhone Dev. Мой вопрос касается управления немодальными окнами. Он сильно отличается от iPhone и модели управления памятью.

Скажем, например, у меня есть окно настроек, я могу использовать что-то подобное для отображения окна:

-(IBAction)showPreferenceController:(id)sender {
  if (!preferenceController) {
  preferenceController = [[PreferenceController alloc]init];
  }
  [preferenceController showWindow:preferenceController]; 
}

Но с этим кодом окно будет оставаться в памяти в течение жизни приложения, потому что окно никогда не открывается.

Чтобы избежать этого, я мог бы также использовать метод, описанный здесь:
stackoverflow.com/questions/1391260/who-owns-an-nswindowcontroller-in-standard-practice
Создайте в PreferenceController a + (id) sharedInstance и откройте окно, используя (void)windowWillClose:(NSNotification *)notification

Я вижу много примеров кода какао, где немодальные окна никогда не выпускаются. Например, здесь: http://www.mattballdesign.com/blog/2008/10/01/building-a-preferences-window/: панель настроек и все подпредставления создаются в awakeFromNib и поэтому будут храниться в памяти в течение всего срока службы приложения.

Если вы возьмете, например, приложение Xcode, немодальных окон много:
- Глобальное окно поиска (CMD + MAJ + F)
- Панель информации о приложении
- Окно помощи
- ...

Я полагаю, что эти окна открываются, когда они закрыты, чтобы сохранить как можно меньше памяти. Я хотел бы, чтобы некоторые советы знали, как лучше всего управлять немодальными окнами в приложении какао. Хранить в памяти? Выпуская как можно скорее? Я знаю, что у Mac много памяти по сравнению с iPhone, но я также думаю, что нехорошо хранить в памяти объекты, которые мы не используем.

Спасибо.

Отредактировано с постом Роба :

Я отправляю -autorelease в окно и устанавливаю свой указатель на nil, чтобы позже я заново создал окно. Это похоже на технику, которую вы цитируете, хотя использование + sharedController для контроллера не связано; Вы можете сделать это независимо от того, есть ли у вас общий контроллер или нет.

Я не знаю, как это сделать без синглтона (+ sharedController).
Я объясняю, что я имею в виду с этим примером:
В приложении Контроллер:

@interface AppController : NSObject <NSApplicationDelegate> {

Реализация:

-(IBAction)showPreferenceController:(id)sender {  
  if (!preferenceController) {
    preferenceController = [[PreferenceController alloc]init];
  }
  [preferenceController showWindow:preferenceController];
}  

В контроллере настроек:

@interface PreferenceController : NSWindowController <NSWindowDelegate>

Реализация:

- (void)windowWillClose:(NSNotification *)notification {
  [self autorelease];self=nil;
}

Сбой при закрытии и повторном открытии после окна: preferenceController освобождается, но не равно нулю. Поэтому мне нужно установить preferenceController в ноль, когда окно закрыто. Нет проблем сделать это с помощью синглтона.
Без синглтона я должен установить appController в качестве делегата окна настроек, чтобы иметь возможность установить preferenceController на ноль, когда окно закрыто. Но мне это не нравится.

Отредактировано с комментариями Престона
Я этого не говорил, но мне нужен только один экземпляр моего немодального окна, даже если мы вызываем -(IBAction)showPreferenceController:(id)sender несколько раз.
Вот почему я проверяю, равен ли preferenceController нулю или нет в appController.
Итак, мне нужно установить preferenceController равным nil в appController, если мы закроем окно.
Таким образом, решение будет:
В AppController , прослушивание NSWindowWillCloseNotification:

- (void)windowWillClose:(NSNotification *)notification {
    if ([notification object] == [preferenceController window]) {
        [preferenceController autorelease];
        preferenceController = nil;
    }
}

Это правильно? Это единственное решение? потому что кажется немного сложным просто управлять моим немодальным окном ...

Ответы [ 2 ]

3 голосов
/ 20 декабря 2009

Вы думаете, все здесь правильно. Утечка памяти - это не нормально, потому что у тебя ее много. Тем не менее, принято не выпускать окна только потому, что они закрываются на Mac. Как правило, вам следует придерживаться их, если вы думаете, что они снова откроются, чтобы избежать затрат на их перезагрузку.

На NSWindow существует две школы мысли: принадлежащие и не принадлежащие. Я из "собственной" школы мысли. Я обычно даю каждому окну владельца, который сохраняет его с помощью ивара и освобождает его при необходимости. Обычно это делегат, иногда это контроллер приложения. В -windowShouldClose: я отправляю -autorelease в окно и устанавливаю свой указатель на ноль, поэтому я воссоздаю окно позже. Это похоже на технику, которую вы цитируете, хотя вопрос о том, использовать или нет +sharedController для контроллера, не связан; Вы можете сделать это независимо от того, есть ли у вас общий контроллер или нет.

Неизвестной школой мысли является использование -setReleasedWhenClosed: NSWindow, чтобы оно автоматически высвобождало себя при закрытии. Я полагаю, что некоторые из окон, на которые вы ссылаетесь, делают это таким образом, когда они предоставляются системой, поскольку может не быть делегата. Это может быть полезно в некоторых видах панелей, но я бы с осторожностью отнесся к этому как к общей схеме. Лучше иметь явное управление памятью почти во всех случаях.

1 голос
/ 21 декабря 2009

Если вы установите флажок «Выпуск при закрытии» для своего окна в Интерфейсном Разработчике или установите его программно, оно само отпустится. Вы также можете сделать так, чтобы делегат окна автоматически высвобождал окно в методе windowShouldClose: Delegate.

Если вы хотите освободить оконный контроллер при закрытии окна, попросите ваш оконный контроллер прослушивать NSWindowWillCloseNotification своего окна и выполните [self autorelease] в этом методе. Я не фанат создания одноэлементного контроллера предпочтений, всегда придерживающегося того, с чем пользователь на практике будет редко взаимодействовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...