Re: Load NIB in dynamically loaded bundle.
Re: Load NIB in dynamically loaded bundle.
- Subject: Re: Load NIB in dynamically loaded bundle.
- From: Rainer Brockerhoff <email@hidden>
- Date: Tue, 20 Nov 2001 12:41:10 -0200
Date: Mon, 19 Nov 2001 13:56:50 -0700
From: Erwin Veugelers <email@hidden>
I'm writing a simple application that parses files from one format and
writes them out in another. I'd like the application to be extensible
with additional formats later on, so I'm playing with dynamically loaded
bundles containing the importer and exporter objects. I would like each
plug-in object to provide the main application with a customized NSView
instance to act as a plug-in specific options panel.
Erwin, I'm doing something quite similar in my application, and it
works there... let's see...
In the main application's "PluginManager" class, the "loadParsers"
method contains:
- (void)loadParsers
{
id p;
NSString* path;
path = [[[NSBundle mainBundle] builtInPlugInsPath]
stringByAppendingString:@"/Plugins.bundle"];
This would be better:
path = [[[NSBundle mainBundle] builtInPlugInsPath]
stringByAppendingPathComponent:@"Plugins.bundle"];
since you shouldn't make assumptions about the path separator.
bundle = [NSBundle bundleWithPath:path];
p = [[[bundle principalClass] alloc] init];
[p loadOptionsView];
...
When the parser is later extracted from the storing array and addressed
with [parser getOptionsView], the method returns nil. If I replace the
line "return optionsView" in SimpleParser with "return [[NSView alloc]
init];", I get a nice (albeit empty) NSView object, but returning the
optionsView IBOutlet connection returns nil.
...
This exact same setup, but with all sources and the additional NIB file
stored in the application bundle (and without the two lines loading the
bundle), works just fine, but as soon as I move the SimpleParser code
and NIB to a separate bundle (in a separate PB project file), the nil
thing happens. The bundle loads fine, because "getName" and "hasOptions"
in "SimpleParser" perform as expected.
I think this indicates that your loadOptionsView (which calls
[NSBundle loadNibNamed:@"SimpleParser.nib" owner:self]) is somehow
getting confused as to where it's loading the nib from. The header
for this call says: "If there is a bundle for owner's class, this
method looks in that bundle for a nib with the given file name.
Otherwise, it looks in the mainBundle."
BTW, the parameter for loadNibNamed: should be @"SimpleParser", not
@"SimpleParser.nib". The extension is appended automatically. But
that shouldn't be the problem.
I'd suggest rewriting your method as:
- (BOOL)loadOptionsView
{
NSBundle* mainBundle = [NSBundle mainBundle];
NSBundle* selfBundle = [NSBundle bundleForClass:[self class]];
NSString* selfPath = [selfBundle bundlePath];
BOOL ok = [NSBundle loadNibNamed:@"SimpleParser.nib" owner:self];
return ok;
}
Put a breakpoint at the return statement, and debug. At the
breakpoint, check that mainBundle and selfBundle don't point at the
same object, and that selfPath is your bundle's pathname, not the
application's pathname. Also, at that point, your IBOutlet should be
connected.
In my application I do it a little different, I have a class method
in the plugin, somewhat like this:
+ (NSView*)makePluginAndReturnView {
SimpleParser* thing = [[SimpleParser alloc] init];
if (thing) {
[NSBundle loadNibNamed:@"myNib" owner:thing];
return [thing getOptionsView];
}
return nil;
}
and I call it from my app like this:
bundle = [NSBundle bundleWithPath:path];
view = [[bundle principalClass] makePluginAndReturnView];
(Well, in fact I load the bundle only after checking its principal
class obeys my plugin protocol, but that shouldn't make any
difference...)
E-mail me in private if you want more details.
--
Rainer Brockerhoff <email@hidden>
Belo Horizonte, Brazil
"Originality is the art of concealing your sources."
http://www.brockerhoff.net/ (updated Oct. 2001)