Failed to render instance of ClassName: The agent threw an exception loading nib in bundle
Asked Answered
M

2

20

When I include my custom IBDesignable view in a storyboard or another nib, the agent crashes and throws an exception because it can't load the nib.

error: IB Designables: Failed to update auto layout status: The agent raised a "NSInternalInconsistencyException" exception: Could not load NIB in bundle: 'NSBundle (loaded)' with name 'StripyView'

Here's the code I use to load the nib:

override init(frame: CGRect) {
    super.init(frame: frame)
    loadContentViewFromNib()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    loadContentViewFromNib()
}

func loadContentViewFromNib() {
    let nib = UINib(nibName: String(StripyView), bundle: nil)
    let views = nib.instantiateWithOwner(self, options: nil)
    if let view = views.last as? UIView {
        view.frame = bounds
        view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
        addSubview(view)
    }
}

The view loads from the nib correctly when I run in the simulator, why won't it display in Interface Builder?

Monte answered 29/2, 2016 at 12:58 Comment(0)
M
44

When Interface Builder renders your IBDesignable views, it uses a helper app to load everything. The upshot of this is that the mainBundle at design time is related to the helper app, and it's not your app's mainBundle. You can see that the path mentioned in the error has nothing to do with your app:

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Overlays

When loading the nib, you're relying on the fact that passing bundle: nil defaults to your app's mainBundle at run time.

let nib = UINib(nibName: String(describing: StripyView.self), bundle: nil)

So instead, you need to pass the correct bundle here. Fix the above line with the following:

let bundle = Bundle(for: StripyView.self)
let nib = UINib(nibName: String(describing: StripyView.self), bundle: bundle)

That will make Interface Builder load your nib from the same bundle as your custom view class.

This applies to anything that's loaded from a bundle by your custom view. For example, localised strings, images, etc. If you're using these in your view, make sure you use the same approach and explicitly pass in the bundle for the custom view class.

Monte answered 29/2, 2016 at 12:58 Comment(4)
Thanks! This is missing from a surprising number of tutorials.Earthshaker
If I could I would have given you 100+ points. I've lost a lot of time with this.Huntingdonshire
Glad I could help, Laura and Joe!Monte
I encountered a similar problem. If this solution doesn't work, try my answer here (remove any orphaned IBOutlets). https://mcmap.net/q/423439/-ib-designables-failed-to-render-and-update-auto-layout-statusGerge
L
4

The same viewpoint with "Josh Heald", We can't pass nil for bundle. And this one for who in object - C:

- (UIView *) loadViewFromNib{
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:bundle];
UIView *v = [[nib instantiateWithOwner:self options:nil]objectAtIndex:0];
return v;
}
Loathing answered 16/5, 2017 at 0:2 Comment(1)
This is about 1 year old, and it isn't the full solution for me, but this got me past the major hurdle, of getting the nib to load. thank you!!!Nephrotomy

© 2022 - 2024 — McMap. All rights reserved.