Инициализация подкласса NSWindowController из пера не использует -initWithCoder:?

Я добавил пользовательский подкласс NSWindowController в свой проект Cocoa и добавил экземпляр моего подкласса в перо моего приложения. Я ожидал увидеть переопределение метода -initWithCoder:, вызванного при загрузке пера, но этого не произошло. Для отладки я добавил обычный метод -init и установил для него точку останова — и, конечно же, я наткнулся на точку останова при загрузке пера.

На самом деле это могло бы сделать некоторые вещи проще для меня (например, установка windowNibName), но я не понимаю, почему Cocoa ведет себя таким образом. Вся документация, которую я прочитал, предполагает, что -initWithCoder: это то место, где я должен переопределять. Почему этот случай отличается?


person Kaelin Colclasure    schedule 15.08.2010    source источник
comment
Почему вы помещаете оконный контроллер в перо? Обычно вы используете оконный контроллер для загрузки пера, и оконный контроллер будет владельцем файла для содержимого пера.   -  person Peter Hosey    schedule 17.08.2010
comment
Этот конкретный оконный контроллер предназначен для листа, который падает поверх главного окна моего приложения. Сделав его владельцем файла пера, которое он загружает, и объектом верхнего уровня в моем пера MainMenu, я могу легко установить IB-соединения с ним из любого места. Работает как часы. :-)   -  person Kaelin Colclasure    schedule 17.08.2010


Ответы (3)


Я предполагаю, что для создания экземпляра вашего оконного контроллера в Interface Builder вы перетащили общий экземпляр NSObject в файл пера, а затем назначили свой собственный подкласс NSWindowController в качестве класса объекта, это правильно? Если это так, то я думаю, что ключевое различие здесь заключается в том, что вы имеете дело с созданием экземпляра универсального объекта, а не пользовательского объекта, включенного в одну из палитр IB.

В большинстве случаев, когда вы создаете и настраиваете объект с помощью IB, настройки, которые вы указываете в различных инспекторах, кодируются с использованием метода encodeWithCoder: при сохранении файла пера. Когда вы затем загружаете этот файл пера в свое приложение, эти объекты инициализируются с использованием метода initWithCoder:.

Однако в случае экземпляра универсального объекта Interface Builder не обязательно знает что-либо о классе объекта, экземпляр которого создается. Поскольку вы можете указать любое имя класса для создания экземпляра, если вы укажете класс, который IB не загрузил через палитру или фреймворк, он не сможет сериализовать этот объект с помощью NSCoding. Поэтому я считаю, что когда вы создаете такой универсальный объект, он инициализируется с использованием init, а не initWithCoder:, потому что он не был сохранен с использованием encodeWithCoder: в первую очередь при сохранении файла пера.

Я не знаю, задокументировано ли это где-нибудь, но я думаю, именно поэтому вы видите разницу. Я также не думаю, что это специфично для NSWindowController, скорее вы увидите такое же поведение любого объекта, созданного как общий NSObject в IB, независимо от конкретного класса.

person Brian Webster    schedule 16.08.2010
comment
Я сделал почти то, что вы описали… за исключением того, что я использовал браузер классов в IB и перетащил экземпляр моего подкласса NSWindowController на верхний уровень моего пера. Это поведение имеет смысл, как вы его описали, и кажется полезной функцией. Жаль, что это не документировано лучше! - person Kaelin Colclasure; 16.08.2010

У меня до сих пор нет формального ответа, почему Cocoa ведет себя именно так, но в практическом использовании вроде бы удобно. Я определил подкласс NSWindowController с помощью следующего метода -init, и он работает как шарм.

- (id)init;
{
    if ((self = [super initWithWindowNibName:@"MumbleMumbleSheet"]) != nil) {
        …
    }
    return self;
}

Если бы вызывался -initWithCoder:, мне пришлось бы выяснить, как выполнить неявное обязательство вызвать метод super -initWithCoder: и при этом получить правильное -windowNibName, используемое для загрузки. Это намного проще.

Я все равно был бы признателен за ссылку на какую-нибудь документацию, в которой говорится, что этот класс отличается, и объясняется, почему и как… Но в отсутствие документации есть эмпирические доказательства.

person Kaelin Colclasure    schedule 16.08.2010
comment
Одна из причин заключается в том, что NSWindowController не нуждается в xib. На самом деле вы можете создать NSWindowController с IB и подключить его оконный выход к любому окну, которое вы хотите, и взять его под контроль. Но вы правы. Я ловлю себя на том, что делаю то же самое, что и вы, все время. В iOS существует соглашение для контроллеров представления: если ваш класс контроллера представления называется XYZViewController, при инициализации он автоматически загружает xib-файл с именем XYZView (или что-то в этом роде). - person Christian Kienle; 11.01.2014

Методы кодера используются для классов, которые были сериализованы и сохранены в файл.

То, что вы делаете здесь, отличается. Вы встраиваете свой класс контроллера в свой исполняемый файл. Это означает, что нет необходимости читать сам класс из файла, поскольку он является частью исполняемого двоичного файла приложения.

При использовании этого класса контроллера вам необходимо предоставить метод инициализации, в котором вы указываете имя файла пера. Почему? Ну, у вас есть скомпилированный класс как часть вашего exe, но вы не знаете, что такое файл пера. Вот как вы даете эти знания.

Подумайте об этом так. Ваш класс контроллера является частью exe. Необходимо установить некоторую связь между ним и файлом пера. Одним из способов было бы просмотреть все файлы пера в поисках ссылок на этот контроллер. Это было бы неэффективно. Укажите имя в инициализации, и все загрузится.

Другими словами, вы извлекли несколько важных уроков из своих экспериментов. Молодец, что так наблюдателен.

person No one in particular    schedule 16.08.2010
comment
Я должен был сделать это более ясным: я загружаю этот экземпляр моего подкласса NSWindowController из пера (ну, теперь xib). Было бы неплохо, если бы мы могли включить сюда изображения, так как это значительно упростило бы описание того, что где находится… - person Kaelin Colclasure; 16.08.2010