UITabBarController в IOS5 выдает исключение UIViewControllerHierarchyInconsistency

#objective-c #uitabbarcontroller #ios5

#objective-c #uitabbarcontroller #ios5

Вопрос:

У меня есть следующий код для UITabBarController:

 NSMutableArray *arr = [[NSMutableArray alloc] init];
tabBarController = [[UITabBarController alloc] init];

FirstViewController *firstview = [[FirstViewController alloc] init];
[tabBarControllerViews addObject:firstview];
[firstview release];

 SecondViewController *secondview = [[SecondViewController alloc] init];
[tabBarControllerViews addObject:secondview];
[secondview release];

[tabBarController setViewControllers:arr animated:YES];
[arr release];

self.view = tabBarController.view;
  

Этот код отлично работает на IOS4. Я попробовал это на бета-версии IOS5 и получаю следующую ошибку при нажатии на элемент UITabBarItem:

 *** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency',
reason: 'child view controller:<FirstViewController: 0x6e03be0> should have parent view
controller:<MainViewController: 0x6816d20> but actual parent is:<UITabBarController: 0x6b0c110>'
  

Ответ №1:

заменить:

 self.view = tabBarController.view;
  

с:

 [self.view addSubview:tabBarController.view];
  

Это также будет обратно совместимо с IOS3 и 4.

Ответ №2:

В моем коде был тот же шаблон (и проблема). Решение Джо у меня не сработало. Глядя на фрагмент, я предполагаю, что вы производите класс от UIViewController, чтобы позволить вам что-то настраивать.

Что нужно сделать здесь, и это довольно просто, это вывести из UITabBarController, а не UIViewController, не создавайте TabBarController, и везде, где вы ссылаетесь на TabBarController, замените self .

5 минут, и вы больше не создаете исключение несоответствия и остаетесь обратно совместимыми с iOS 4. Вы все еще можете выполнить все свои настройки в своем производном классе (манипулировать навигационным контроллером и т.д.).

Если вы создали сложную производную от UIViewController, которую вам нужно использовать, это может потребовать больше работы.

Одна небольшая ошибка — если вы переопределите loadView, вы обнаружите, что он вызывается во время инициализации для UITabBarController. Затрудняет установку элементов до loadView, поэтому вам может потребоваться разделить вашу инициализацию.

Удачи!

Комментарии:

1. Проблема с заменой self.view = TabBarController.view; на self.view addSubview: TabBarController.view, как предложено ниже, заключается в том, что у вас все та же несогласованность в иерархии контроллеров представления, вы взяли представление с одного контроллера представления и вставили его в другой контроллер представления. Если Apple ужесточит проверку для этих случаев, этот код в какой-то момент в будущем завершится ошибкой. Посмотрите видео сеанса 102 с WWDC 2011 на iTunes U для получения дополнительной информации.

2. Полностью согласен с Мэттом. Создание подкласса из UITabBarController вместо UIViewController помогло решить проблему, а также сохранить обратную совместимость.

3. @настройки интерфейса ViewController: UITabBarController <UITabBarControllerDelegate>

4. Я нахожусь в процессе решения этой же проблемы… Я не закончил, но похоже, что это, вероятно, правильный способ думать об этом. Однако я понимаю, почему я в замешательстве… В документах для UITabBarController сказано — прямо в быстрой справке: » Этот класс не предназначен для создания подклассов. Вместо этого вы используете его экземпляры как есть, чтобы представить интерфейс, который позволяет пользователю выбирать между различными режимами работы.» Устарели ли документы? Я пытаюсь обновить приложение, которое я написал и не трогал в течение года, и я предполагаю, что именно поэтому я не стал его подклассом в первую очередь.

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

Ответ №3:

Вы не можете отправить или представить UITabBarViewController. Является ли ваш первый контроллер просмотра UITabBarController?

Ответ №4:

Я боролся с той же проблемой.

При создании нового приложения с основными деталями (без раскадровки) вы можете увидеть эти коды ниже из AppDelegate.m.

  MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:@"MasterViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
  

«НЕ ЗАВИСЕТЬ ОТ MainWindow»
Просто запустите свой собственный ViewController и установите для него значение делегировать.
И не забудьте отсоединить view от MainWindow.xib, иначе view будет вызван 2 раза.