Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Debugging UIKit crash [UINavigationController initWithRootViewController]

Xcode 7.0.1

Update:

The latest thing I tried was to break down creation of the UINavigationController thus:

  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];

Doing this the crash is now on

[self.window makeKeyAndVisible];

but the trace is exactly the same.

I've also tried this with a vanilla ViewController by changing

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

Same result...

Original Post:

I have a crash which I am struggling to understand - Here is the lldb trace: Note the index of 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

This is a mature app which has been building and running for some time but in the current XCode the above happens.

As you can see there is a call to UINavigationController:initWithRootViewController - here is the code:

- (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
}

I have tried a few things after looking at some similar questions and answers here on SO.

  • I've heard that this can happen if View controller-based status bar appearance is set to YES in the Info.plist - so I've set that to NO / YES

  • I've heard that some UIGestureRecognizers can cause issues - So I've examined the XIB and ensured that there are none effecting this view controller.

  • I've heard that if the root view controller isn't fully initialised it can be problematic - so I've delayed the call to the UINavigationController by 1 second

  • I've mis-trusted ProjectsViewController - so I've substituted it for a vanilla UIViewController thus:

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

Any insight much appreciated; either in what might be causing the issue or in a technique to debug that might throw some light on the issue.

like image 928
Damo Avatar asked Oct 01 '15 16:10

Damo


2 Answers

I think that you are focusing on the wrong piece of code. As you mentioned, it crashes on the [self.window makeKeyAndVisible] line, however, what's probably causing the crash is the fact that this line causes the ProjectsViewController and the UINavigationController objects to load and be presented to the user. Looking at the crash log you posted, this is the part you should be investigating:

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

You can see here that iOS attempts to layout the UINavigationBar's subviews and then to remove an object at an index that is probably NSNotFound (which would result in NSIntegerMax, which matches the index you mentioned in your crash log).

In order to further research the crash, I would recommend following these steps:

  1. Replace your ProjectsViewController instance with a UIViewController instance without a custom .xib file. (I read in your original post that you have already tried this, but still, I would recommend doing this as the first step in order to eliminate additional issues, if there is more than one, on the way to fully resolving the crash). It's important to make sure that you are not using your .xib file at this point, as it may be what's causing the crash (if there are any mis-linked outlets or similar issues).
  2. Does your navigation bar have any items displayed in it? Again, I noticed you mentioned in the comments that it doesn't, but I would double check to see if maybe there's a code section in which items are added to the bar under certain conditions and removed if they aren't met. This can cause the crash, if the items are attempted to be removed from an invalid index.
  3. Try searching for places in your code that specifically call removeObjectAtIndex or any other NSMutableArray related call that may be called during the load and display process of your initial view controller. Add a breakpoint in these places to see if they are reached during the initial loading process. If so, try adding a test there to make sure that the index you are trying to remove an object from is larger than or equal to zero and is smaller than the array's size. That way, if index you are trying to access is NSNotFound it will at least not cause the app to crash (a good practice regardless of the current crash). If this ends up resolving the issue, you can then investigate the issue further and try to understand why the NSNotFound is actually received as the index and fix the issue logically.

I hope one of these steps can help identify and resolve your issue. Good Luck!

like image 170
Rony Rozen Avatar answered Nov 07 '22 19:11

Rony Rozen


UINavigationController is a stack where you can only push and pop UIViewController. You should pass a UIViewController on initiating navigation controller. But if you don't know RootViewController then you can do like this.

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];
like image 1
Zahid Avatar answered Nov 07 '22 17:11

Zahid