Search code examples
iosobjective-cunrecognized-selector

Unrecognized selector sent to instance on array assignment


I am following this guide to create simple iPhone app.

But when I try to launch it, it fails with unrecognized selector sent to instance Exception.

I did debugging, and failure occurs on this line:

masterController.bugs = bugs;

of method (didFinishLaunchingWithOptions).

That's my first app, so it should be something obvious. The only changes that I did to code on tutorial: added #import <UIKit/UIKit.h>, because otherwise it does not allow code to be compiled.

Full method code:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    RWTScaryBugDoc *bug1 = [[RWTScaryBugDoc alloc] initWithTitle:@"Potato Bug" rating:4 thumbImage:[UIImage imageNamed:@"potatoBugThumb.jpg"] fullImage:[UIImage imageNamed:@"potatoBug.jpg"]];
    RWTScaryBugDoc *bug2 = [[RWTScaryBugDoc alloc] initWithTitle:@"House Centipede" rating:3 thumbImage:[UIImage imageNamed:@"centipedeThumb.jpg"] fullImage:[UIImage imageNamed:@"centipede.jpg"]];
    RWTScaryBugDoc *bug3 = [[RWTScaryBugDoc alloc] initWithTitle:@"Wolf Spider" rating:5 thumbImage:[UIImage imageNamed:@"wolfSpiderThumb.jpg"] fullImage:[UIImage imageNamed:@"wolfSpider.jpg"]];
    RWTScaryBugDoc *bug4 = [[RWTScaryBugDoc alloc] initWithTitle:@"Lady Bug" rating:1 thumbImage:[UIImage imageNamed:@"ladybugThumb.jpg"] fullImage:[UIImage imageNamed:@"ladybug.jpg"]];
    NSMutableArray *bugs = [NSMutableArray arrayWithObjects:bug1, bug2, bug3, bug4, nil];

    UINavigationController *navController = (UINavigationController *) self.window.rootViewController;
    MasterViewController *masterController = [navController.viewControllers objectAtIndex:0];
    masterController.bugs = bugs;

    // Override point for customization after application launch.
    UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
    UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
    navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
    splitViewController.delegate = self;
    return YES;
}

Full stacktrace:

2015-01-19 10:06:10.489 ScaryBugs[6603:5904685] -[UINavigationController setBugs:]: unrecognized selector sent to instance 0x7d116690
2015-01-19 10:06:10.491 ScaryBugs[6603:5904685] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationController setBugs:]: unrecognized selector sent to instance 0x7d116690'
*** First throw call stack:
(
    0   CoreFoundation                      0x00951946 __exceptionPreprocess + 182
    1   libobjc.A.dylib                     0x005daa97 objc_exception_throw + 44
    2   CoreFoundation                      0x009595c5 -[NSObject(NSObject) doesNotRecognizeSelector:] + 277
    3   CoreFoundation                      0x008a23e7 ___forwarding___ + 1047
    4   CoreFoundation                      0x008a1fae _CF_forwarding_prep_0 + 14
    5   ScaryBugs                           0x000f65a8 -[AppDelegate application:didFinishLaunchingWithOptions:] + 1288
    6   UIKit                               0x00cfe97c -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 291
    7   UIKit                               0x00cff687 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2869
    8   UIKit                               0x00d02c0d -[UIApplication _runWithMainScene:transitionContext:completion:] + 1639
    9   UIKit                               0x00d1b7d0 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke + 59
    10  UIKit                               0x00d0181f -[UIApplication workspaceDidEndTransaction:] + 155
    11  FrontBoardServices                  0x032919de __37-[FBSWorkspace clientEndTransaction:]_block_invoke_2 + 71
    12  FrontBoardServices                  0x0329146f __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 54
    13  FrontBoardServices                  0x032a3425 __31-[FBSSerialQueue performAsync:]_block_invoke + 26
    14  CoreFoundation                      0x008751c0 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 16
    15  CoreFoundation                      0x0086aad3 __CFRunLoopDoBlocks + 195
    16  CoreFoundation                      0x0086a238 __CFRunLoopRun + 936
    17  CoreFoundation                      0x00869bcb CFRunLoopRunSpecific + 443
    18  CoreFoundation                      0x008699fb CFRunLoopRunInMode + 123
    19  UIKit                               0x00d011e4 -[UIApplication _run] + 571
    20  UIKit                               0x00d048b6 UIApplicationMain + 1526
    21  ScaryBugs                           0x000f853d main + 141
    22  libdyld.dylib                       0x02cb7ac9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

Debugger info, before failure:

Debugger info, before failure


Solution

  • UINavigationController *navController = (UINavigationController *) self.window.rootViewController;
    MasterViewController *masterController = [navController.viewControllers objectAtIndex:0];
    

    The problem is here. The code assumes that the rootViewController of the window is a navigation controller, but it's probably actually your split view controller. You then request the first view controller held by this supposed-but-not-actual navigation controller, which is the navigation controller itself. Of course, the navigation controller doesn't have a bugs property, so assigning to it causes the exception.

    What you probably want to do instead is get a reference to the split view controller's first view controller, then get the returned navigation controller's first view controller, which is your actual MasterViewController.