How to load a XIB with a top-level ViewController?

拈花ヽ惹草 提交于 2019-12-23 08:47:34

问题


I've got a nib with a view controller root element like this:

so I can position elements relative to the top and bottom layout guides using auto-layout.

When I first tried to load this nib using

SearchViewControllerPro* searchViewController = [[SearchViewControllerPro alloc]initWithNibName:@"SearchViewControllerPro" bundle:[NSBundle mainBundle]];

I got the following run-time exception:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "SearchViewControllerPro" nib but the view outlet was not set.'

Googling the error it was pointed out to me, that the file owner of the xib needed to be set to the class of my view controller and the view outlet had to be set to the view object in the xib. If I do so, then I get the following run-time error:

Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'A view can only be associated with at most one view controller at a time! View > is associated with . Clear this association before associating this view with .'

Does not come as a surprise since the view is associated to both the file owner and the top-level view controller of the nib. But how can I tell the run-time that they are both in fact the very same thing instead of two separate entities?

Edit: When I try to unpck the ViewController from the nib like so,

NSArray* xibContents = [[NSBundle mainBundle] loadNibNamed:@"SearchViewControllerPro" owner:nil options:nil];
SearchViewControllerPro* mapSearchViewController = [xibContents lastObject];

, it does no good either:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key view.

Temporary solution:

I found a solution, but it is not pretty. Despite the structure as shown in IB, the view controller is not the last object in the xib. So I have:

__block SearchViewControllerPro* mapSearchViewController = nil;
[xibContents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isKindOfClass:[SearchViewControllerPro class]]) {
        mapSearchViewController = obj;
    }
}];

and this seems to work without run-time crashes. However, it's everything but clean code.


回答1:


how can I tell the run-time that they are both in fact the very same thing instead of two separate entities?

You can't because they are not the same thing. You have created two SearchViewControllerPro intstances.

You need to either alloc-init a SearchViewControllerPro instance or unarchive one from a nib.

If you decide to create the ViewController in the nib the usual way to access it is the same way you would access any other item (view, button, textfield) that you create in a nib.

Add an outlet to the FilesOwner object, hook up the connection in interface builder and be sure to pass the object when you unarchive the nib.

eg If you want the Object that unarchives the nib to be FilesOwner:

[[NSBundle mainBundle] loadNibNamed:@"SearchViewControllerPro" owner:self options:nil];



回答2:


The following works as well and (at least to me) is a little more explicit that creating an outlet for the ViewController:

NSArray* xibContents = [[NSBundle mainBundle] loadNibNamed:@"SearchViewControllerPro" owner:nil options:nil];
SearchViewControllerPro* mapSearchViewController = [xibContents objectAtIndex:0];



回答3:


if (isIPad)
{
    [[NSBundle mainBundle] loadNibNamed:@"ABC_iPad" owner:self
options:nil];

}
else{
    [[NSBundle mainBundle] loadNibNamed:@"ABC_iPhone" owner:self options:nil];

}


来源:https://stackoverflow.com/questions/19001808/how-to-load-a-xib-with-a-top-level-viewcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!