Подтвердить что ты не робот

Отладка сбой UIKit [UINavigationController initWithRootViewController]

Xcode 7.0.1

Обновление:

Последнее, что я пробовал, - сломать создание UINavigationController, таким образом:

  self.viewController = [[ProjectsViewController alloc] initWithNibName:@"ProjectsViewController_iPhone" bundle:nil];
  self.navigationController = [[UINavigationController alloc] init];
  [self.navigationController setViewControllers:@[self.viewController]];
  self.window.rootViewController = self.navigationController;
  [self.window makeKeyAndVisible];

Выполнение этого сбоя теперь включено

[self.window makeKeyAndVisible];

но трассировка точно такая же.

Я также пробовал это с помощью vanilla ViewController, изменив

[self.navigationController setViewControllers:@[[[UIViewController alloc] init]]];

Тот же результат...

Оригинальное сообщение:

У меня есть сбой, который я пытаюсь понять. Вот трассировка lldb: Обратите внимание на индекс 2147483648

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM removeObjectAtIndex:]: index 2147483648 beyond bounds [0 .. 2]'
*** First throw call stack:
(
0   CoreFoundation                      0x035eaa94 __exceptionPreprocess + 180
1   libobjc.A.dylib                     0x03084e02 objc_exception_throw + 50
2   CoreFoundation                      0x034f92ed -[__NSArrayM removeObjectAtIndex:] + 445
3   UIKit                               0x018c20b2 -[UIView(Hierarchy) bringSubviewToFront:] + 260
4   UIKit                               0x0193daeb -[UINavigationBar layoutSubviews] + 3692
5   UIKit                               0x018d716b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 813
6   libobjc.A.dylib                     0x03099059 -[NSObject performSelector:withObject:] + 70
7   QuartzCore                          0x0096e60c -[CALayer layoutSublayers] + 144
8   QuartzCore                          0x0096228e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 388
9   QuartzCore                          0x00970b2c -[CALayer(CALayerPrivate) layoutBelowIfNeeded] + 44
10  UIKit                               0x018c4dca -[UIView(Hierarchy) layoutBelowIfNeeded] + 1244
11  UIKit                               0x01a117cf __74-[UINavigationController _positionNavigationBarHidden:edge:initialOffset:]_block_invoke + 36
12  UIKit                               0x018caca6 +[UIView(Animation) performWithoutAnimation:] + 82
13  UIKit                               0x01a1178d -[UINavigationController _positionNavigationBarHidden:edge:initialOffset:] + 922
14  UIKit                               0x01a1194c -[UINavigationController _positionNavigationBarHidden:edge:] + 326
15  UIKit                               0x01a12d5f -[UINavigationController _positionNavigationBarHidden:] + 49
16  UIKit                               0x01a1104a -[UINavigationController setNavigationBar:] + 1224
17  UIKit                               0x01a10a38 -[UINavigationController _navigationBarHiddenByDefault:] + 156
18  UIKit                               0x01a10997 -[UINavigationController navigationBar] + 41
19  UIKit                               0x01a17805 -[UINavigationController loadView] + 230
20  UIKit                               0x019d3338 -[UIViewController loadViewIfRequired] + 138
21  UIKit                               0x019d3cf1 -[UIViewController view] + 35
22  UIKit                               0x01a22226 -[UINavigationController pushViewController:transition:forceImmediate:] + 615
23  UIKit                               0x01a21e27 __54-[UINavigationController pushViewController:animated:]_block_invoke + 351
24  UIKit                               0x01a21c83 -[UINavigationController pushViewController:animated:] + 786
25  UIKit                               0x01a07be2 -[UINavigationController initWithRootViewController:] + 140
26  DELETIA                             0x0012954e -[AppDelegate application:didFinishLaunchingWithOptions:] + 1214

Это зрелое приложение, которое было создано и работает некоторое время, но в текущем XCode это происходит.

Как вы видите, есть вызов UINavigationController: initWithRootViewController - вот код:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// deletia - non UIKit code

  self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  self.window.tintColor = [UIColor darkGrayColor];

  self.viewController = [[ProjectsViewController alloc] initWithNibName:@"ProjectsViewController_iPhone" bundle:nil];

  self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];

// deletia - but the app crashes on the above line
}

Я пробовал несколько вещей, посмотрев на некоторые подобные вопросы и  ответы здесь на SO.

  • Я слышал, что это может произойти, если в панели состояния View Control внешний вид установлен в YES в Info.plist - поэтому я установил для него значение NO/ ДА

  • Я слышал, что некоторые UIGestureRecognizers могут вызывать проблемы. Итак, я изучил XIB и гарантировал, что никаких действий с этим контроллером представления не будет.

  • Я слышал, что если контроллер корневого представления не полностью инициализирован это может быть проблематично - поэтому я отложил вызов UINavigationController на 1 секунду

  • Я неправильно доверял ProjectViewController - поэтому я заменил его на ванильный UIViewController, таким образом:

    self.navigationController = [[UINavigationController alloc] initWithRootViewController:[[UIViewController alloc] init]];
    

Любое понимание очень ценится; либо в том, что может вызвать проблему, либо в методе отладки, что может вызвать некоторый свет в этом вопросе.

4b9b3361

Ответ 1

Я думаю, что вы фокусируетесь на неправильном фрагменте кода. Как вы уже упоминали, он падает на строку [self.window makeKeyAndVisible], однако, вероятно, причиной сбоя является тот факт, что эта строка вызывает загрузку объектов ProjectsViewController и UINavigationController и их представление пользователю. Глядя на журнал сбоев, который вы опубликовали, это та часть, которую вы должны исследовать:

2   CoreFoundation                      0x034f92ed -[__NSArrayM removeObjectAtIndex:] + 445
3   UIKit                               0x018c20b2 -[UIView(Hierarchy) bringSubviewToFront:] + 260
4   UIKit                               0x0193daeb -[UINavigationBar layoutSubviews] + 3692

Здесь вы можете увидеть, что iOS пытается компоновать подвижки UINavigationBar, а затем удалить объект с индексом, который, вероятно, NSNotFound (что приведет к NSIntegerMax, который соответствует индексу, указанному в вашем журнале сбоев).

Чтобы продолжить исследование сбоя, я бы рекомендовал выполнить следующие шаги:

  • Замените экземпляр ProjectsViewController экземпляром UIViewController без специального файла .xib. (Я прочитал в своем оригинальном посте, что вы уже пробовали это, но все же я бы рекомендовал сделать это в качестве первого шага, чтобы устранить дополнительные проблемы, если их больше, чем на пути полного разрешения аварии). Важно убедиться, что вы не используете ваш .xib файл на этом этапе, так как это может быть причиной сбоя (если есть какие-либо неправильно связанные розетки или подобные проблемы).
  • В вашей навигационной панели есть какие-либо элементы, отображаемые в нем? Опять же, я заметил, что вы упомянули в комментариях, что это не так, но я бы дважды проверял, может ли быть раздел кода, в котором элементы добавляются в панель при определенных условиях и удаляются, если они не выполняются. Это может привести к сбою, если элементы будут удалены из недопустимого индекса.
  • Попробуйте найти места в коде, которые специально вызывают removeObjectAtIndex или любой другой связанный с ним вызов NSMutableArray, который может быть вызван во время загрузки и отображения вашего исходного контроллера представления. Добавьте точку останова в эти места, чтобы увидеть, достигнуты ли они во время начальной загрузки. Если да, попробуйте добавить туда тест, чтобы убедиться, что индекс, который вы пытаетесь удалить из объекта, больше или равен нулю и меньше размера массива. Таким образом, если индекс, к которому вы пытаетесь получить доступ, NSNotFound, он по крайней мере не приведет к сбою приложения (хорошая практика, независимо от текущего сбоя). Если это решит проблему, вы можете продолжить исследование проблемы и попытаться понять, почему NSNotFound фактически получен как индекс и исправить проблему логически.

Я надеюсь, что один из этих шагов поможет определить и решить проблему. Удачи!

Ответ 2

UINavigationController - это стек, в который вы можете только нажать и нажать UIViewController. Вы должны передать UIViewController для запуска навигационного контроллера. Но если вы не знаете RootViewController, вы можете сделать это следующим образом.

self.viewController = [[ProjectsViewController alloc] initWithNibName:@"ProjectsViewController_iPhone" bundle:nil];
  self.navigationController = [[UINavigationController alloc] init];
  [self.navigationController pushViewController:self.viewController animated:NO];
  self.window.rootViewController = self.navigationController;
  [self.window makeKeyAndVisible];