stevendesu
stevendesu

Reputation: 16791

How to load a `.xib` / `.nib` file within a framework?

I'm working on an iOS library as a Cocoa Pod. In this library, I have a custom view:

@interface PlayerView : UIView

@property (strong, nonatomic) IBOutlet UIView *contentView;

@end
@implementation PlayerView

- (instancetype) initWithCoder:(NSCoder*)coder
{
    self = [super initWithCoder:coder];
    [self initialize];
    return self;
}

- (instancetype) initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    [self initialize];
    return self;
}

- (void)initialize
{
    [[NSBundle mainBundle] loadNibNamed:@"PlayerView" owner:self options:nil];
    [self addSubview:contentView];
}

@end

In this case contentView is the entire View defined in the .xib, which includes an image and a label.

When I build my demo app (and the library) the app runs, but when it comes time to display this view I get the following error:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/stevenbarnett/Library/Developer/CoreSimulator/Devices/EC244A5F-CE57-4CCD-9BB4-CDC834D74812/data/Containers/Bundle/Application/446EB609-B663-4BD5-8F8D-F22D03BC0B18/bfsdk_Example.app> (loaded)' with name 'PlayerView''

Inspecting the .app file by hand, the PlayerView.nib file can be found buried in the Frameworks/bfsdk.framework directory, but I'm guessing since it's not at the root it isn't being located:

enter image description here enter image description here

I've verified:

How can I load a .xib file that's within my library from a class that's within my library when running an app that just includes my library as a .framework?

I believe I could get it working if I manually specified the path to the file with something like:

NSString* resourcePath = [[NSBundle mainBundle] pathForResource:@"bfsdk" ofType:@"framework"];
[[NSBundle mainBundle] loadNibNamed:[resourcePath stringByAppendingPathComponent:@"PlayerView"]];

However I don't like that this has me hard-coding my framework's name into one of my classes. If I change the name in a year I don't want everything to break because of this one buried line of code that no one remembers exists.

Upvotes: 0

Views: 490

Answers (1)

Tiran Ut
Tiran Ut

Reputation: 1056

It should be enough to use

[NSBundle bundleForClass:[self class]] instead of [NSBundle mainBundle]

So basically [NSBundle mainBundle] returns bundle for current module which is your app, but not the actual framework

Here you can find more details [NSBundle bundleForClass:[self class]]] what does that mean?

Upvotes: 1

Related Questions