2010-08-15 5 views
4

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

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

+0

Почему вы устанавливаете контроллер окна в наконечник? Обычно вы используете оконный контроллер для * загрузки * nib, а оконный контроллер будет владельцем файла для содержимого nib. –

+0

Этот конкретный оконный контроллер предназначен для листа, который опускается поверх главного окна моего приложения. Сделав его владельцем файла загружаемого наконечника, и объект верхнего уровня в моем MainMenu nib, я могу легко сделать IB-соединения с ним из любого места. Отлично работает. :-) –

ответ

4

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

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

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

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

+0

Я сделал почти то, что вы описали ... за исключением того, что я использовал браузер классов в IB и перетащил экземпляр моего подкласса NSWindowController в верхний уровень моего ножа. Такое поведение имеет смысл, поскольку вы описали его, и это кажется полезной функцией. Жаль, что это не лучше документировано! –

0

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

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

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

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

+0

Одна из причин заключается в том, что NSWindowController не нуждается в xib. Фактически вы можете создать NSWindowController с IB и подключить его выход к окну в любое нужное окно и «взять на себя управление» над ним. Но вы правы. Я нахожу, что делаю то же самое, что и вы все время. В iOS существует соглашение для контроллеров представлений. Если ваш класс контроллера вида называется XYZViewController, в init он автоматически загружает xib-файл с именем XYZView (или что-то в этом роде). –

0

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

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

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

Думайте об этом таким образом. Класс контроллера является частью exe. Некоторая связь между ним и файлом nib должна быть выполнена. Один из способов - просмотреть все файлы nib, которые ищут ссылки на этот контроллер. Это было бы неэффективно. Укажите имя в init и все загрузочные файлы.

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

+0

Я должен был сделать это более ясным: я * загружаю этот экземпляр моего подкласса NSWindowController из nib (ну, теперь xib). Было бы неплохо, если бы мы могли включать изображения здесь, так как это могло бы описать, что именно там намного проще ... –

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