Exception when using NSMainNibFile

I need to load a particular NIB file at launch (using NSMainNibFile) but always get an exception (this class is not key value coding-compliant for the key ...).


To test things, I create a new 'Single View App' project, created a new UIViewController subclass (with the "Also create XIB file" checkbox checked) and set NSMainNibFile to the new created NIB.


Same issue: '[<UIApplication 0x7fa89d000000> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key view.'


View outlet is correctly linked and File Owner class is correctly set. So after one day of investiguation, your suggestions would be appreciated.


Many thanks!!!!

Replies

You set File's Owner to what? The view controller's class? If so, the error message is telling you that the File's Owner is actually the UIApplication object (which doesn't have a "view" property like UIViewController does). That's because you don't have control of what the object is in this case, and you have to use the object you're given: UIApplication.shared. Setting the File's Owner class in the XIB file to the view controller's class is (effectively) just lying to yourself. 🙂


If that's so, then it's not clear how to go about connecting your view controller to your view. One possibility might be to put a view controller object in the XIB itself (which is sort of what a storyboard does), but you're not going to be relying on File's Owner for the view in the usual way.


>> set NSMainNibFile to this new UIviewController class


Technically, no. It needs to specify the name of the NIB file, not the name of the view controller class. That probably is the same thing in this case, but you should keep the difference in mind.


There is also the possibility that a main NIB file needs to contain some standard set of resources beyond just a view. I don't know offhand whether this is documented anywhere, but if dealing with your File's Owner issue doesn't solve the problem, you might try to search the web on this question too.

Which version Xcode are you working with?


Is mainStoryboard still keyed as main by name in Info.plist?

I'm not sure I perfectly understand what you mean in you first paragraph but since Xcode gives you the option to also create the XIB when subclassing UIVIewController, the XIB should be properly set, no?


Correct, I set NSMainNibFile to the NIB file, not the class.

Sorry, I realize I didn't say this right.


When you create a XIB file, you change the class of the File's Owner pseudo-object in the XIB to that of the intended owner object. The actual owner object is instantiated before the NIB file is loaded, and a pointer passed to the NIB loading process to be set as the actual File's Owner reference.


For a normal view controlled by a view controller, it's up to you to create an instance of the correct view controller class (the class that you put in the XIB for File's Owner). However, in the case of a main NIB, you don't create the owner object, so you don't control its class.


So, the error message tells you that iOS used the UIApplication object as owner of the main NIB, and this did not match the File's Owner class you put there.


I found an old iOS app of mine that didn't use storyboards. What I actually did (which I suppose was normal practice years ago, though I don't remember) was to NOT have a main nib specified in info plist. Instead, there was just a series of view XIBs, one of which was intended as the initial display. In my applicationDidFinishLaunching method, I had code like this (Obj-C in those days, of course):


  self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  myRootViewController = [[UITabBarController alloc] init];
  myRootViewController.viewControllers = …;
  self.window.rootViewController = myRootViewController;


Maybe you should try something like that, but also loading the initial NIB manually.

The project I want to modify to use NSMainNibFile currently use the code you listed. :-)


It would be easier to leave the project like this but I now want to understand the issue. I think I will open Technical Support Incident which will expire very soon anyway.