initWithNibName либо вызывается дважды, либо загружается неправильный xib

Я программирую приложение Какао и хочу, чтобы приложение работало как своего рода мастер. Итак, в главном окне у меня есть настраиваемое представление, которое взаимодействует с пользователем и переключается с экрана входа на экран активации устройства по мере прохождения этапов мастера. В настоящее время я переопределил метод awakeFromNib WizardViewController:

- (void)awakeFromNib{
   //If no redirect request save, add first view: ID Login
   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
   NSString *tokenRequest = [defaults objectForKey:@"redirectRequestToken"];
   if (!tokenRequest){
       SignInWithIDViewController *signInViewController = [[SignInWithIDViewController alloc] initWithNibName:@"SignInWithIDViewController" bundle:nil];
       [wizardView addSubview:[signInViewController view]];
   } else {
    NSLog(@"Have already logged in.");
   }
}

Как есть, initWithNibName в SignInIDViewController вызывается дважды, один раз явно мной и еще раз при загрузке представления (предположительно через loadView). Однако, если я просто вызываю init, тогда имя initWithNib вызывается только один раз, но загружается неправильный файл xib (из класса DeviceActivationViewController). Кажется, я не могу понять, что я делаю неправильно, потому что signInViewController не должен запускаться дважды, но мне нужен правильный файл xib в IB для отображения.

Единственный другой метод, который у меня есть в этом классе в настоящее время, который не является IBAction пользовательского интерфейса, - это сгенерированный метод initWithNibName плюс добавленный оператор NSLog.


person Katie    schedule 31.05.2012    source источник
comment
Как узнать, что initWithNibName вызывается дважды? Какой результат вы видите?   -  person rdelmar    schedule 31.05.2012
comment
Когда вы создаете новый подкласс NSViewController, initWithNibName автоматически генерируется со следующим кодом: code- (id) initWithNibName: (NSString *) nibNameOrNil bundle: (NSBundle *) nibBundleOrNil {self = [super initWithNibName: nibName]; if (self) {// Здесь код инициализации. } return self; } Поэтому я добавил NSLog, чтобы отслеживать это. Это также влияет на функциональность других методов, а именно, мой awakeFromNib вызывается дважды в двух разных экземплярах, которые я знаю, потому что каждый экземпляр открывает сервер на другом порту.   -  person Katie    schedule 31.05.2012
comment
Просто чтобы прояснить последнее предложение: мой awakeFromNib вызывается один раз из каждого экземпляра. Всего два.   -  person Katie    schedule 31.05.2012
comment
По опубликованной вами информации сложно сказать, почему это происходит. Я сделал небольшое тестовое приложение, которое выделяет initWithNibName контроллер мастера из делегата приложения (устанавливая представление содержимого главного окна на представление контроллера мастера), а затем помещал код, который вы опубликовали выше, в методы initWithNibName или awakeFromNib контроллера мастера. , и я не видел дважды инициализацию SignInViewController. Делали ли вы что-нибудь еще в файле xib, кроме заполнения ваших пользовательских представлений любыми вложенными представлениями, которые вам нужны?   -  person rdelmar    schedule 01.06.2012
comment
Я понимаю, что трудно понять, что я говорю, но с классами 4+ я не хотел вставлять весь код. Тем не менее, спасибо, что посмотрели на это и попробовали. В настоящее время в моем MainMenu.xib ничего нет и по умолчанию используется WizardViewController, который содержит окно, настраиваемый вид и следующую кнопку. (Этот initWithNibName вызывается только один раз.) SignInWithIDViewController.xib имеет WebView и кнопку в настраиваемом представлении.   -  person Katie    schedule 01.06.2012
comment
Вы не добавляли никаких объектов (синих кубиков) в IB? И как создать экземпляр WizardViewController   -  person rdelmar    schedule 01.06.2012
comment
Код в моем делегате приложения загружает WizardViewController.xib: code if (! Self.window) [NSBundle loadNibNamed: @WizardViewController owner: self]; [self.window makeKeyAndOrderFront: сам]; Я добавил объекты (кубы) в каждый файл xib, сделал их подклассами их контроллеров и установил выходные соединения с этими объектами. Что-то не так? Обычно, если я пытаюсь подключиться с помощью владельца файла, у меня возникают проблемы с подключениями действий.   -  person Katie    schedule 01.06.2012


Ответы (1)


Я думаю, что создание объектов в IB (синие кубики) и создание их экземпляров в коде - это проблема. Если вы создали для них объекты в IB, тогда они будут созданы в awakeFromNib, вам также не следует вызывать для них alloc init в коде - это создаст новый экземпляр.

У меня нет большого опыта использования контроллеров представления в OSX, но кажется, что вы не можете подключить IBActions к контроллеру представления (как владельцу файла). Я заставил это работать подклассом настраиваемого представления (которое создается для вас, когда вы добавляете контроллер представления), изменить класс этого представления на ваш новый подкласс и поместить методы действия в этот класс. Похоже, что это должно быть что-то, что будет обрабатываться контроллером представления, но я думаю, что это не работает, как-то связано с тем, что контроллер представления не находится в цепочке ответчика в OSX (тогда как я думаю, что это в iOS).

После редактирования: после обхода проблем с управлением памятью, я думаю, что нашел лучший способ сделать это. Вы можете и, вероятно, должны (в соответствии с парадигмой Apple MVC) поместить методы кнопок в класс контроллера представления, а не в представление, как я сказал выше. Фактически вы можете подключить IBActions к контроллеру представления (как владелец файла), вам просто нужно убедиться, что контроллер представления сохранен, когда вы создаете его экземпляр в коде. Для этого вам нужно сделать signInViewController свойством в любом классе, в котором вы создаете экземпляр класса SignInViewController, и использовать «сохранить» в объявлении свойства. Тогда вам не нужно (и не нужно) создавать какие-либо синие кубы в IB.

person rdelmar    schedule 01.06.2012
comment
Спасибо! Это заняло у меня немного времени, но я исключил, что initWithNibName вызывается дважды, используя ваш ответ, но теперь в SignInWithIDViewController практически нет ничего (кроме init и dealloc) - это кажется большой пустой тратой места. Есть ли способ удалить SignInWithIDViewController и просто иметь подкласс NSView? - person Katie; 01.06.2012
comment
@Katie, я думаю, вам следует использовать контроллер представления, но поместите туда IBActions - подробности см. В моем отредактированном ответе. - person rdelmar; 03.06.2012
comment
Да, похоже, это сработало. Я думаю, что на самом деле это было так же просто, как убедиться, что владельцем файла xib был соответствующий класс контроллера представления. Спасибо! - person Katie; 04.06.2012