问题
In a document based Cocoa app, I am instantiating several objects (plugins) from external bundles using:
- (NSMutableArray *)getPluginsOfType:(Class)type;
{
NSBundle *main = [NSBundle mainBundle];
NSArray *allPlugins = [main pathsForResourcesOfType:@"bundle" inDirectory:@"../PlugIns"];
NSMutableArray *availablePlugins = [NSMutableArray array];
for (NSString *path in allPlugins)
{
NSBundle *pluginBundle = [NSBundle bundleWithPath:path];
[pluginBundle load];
Class principalClass = [pluginBundle principalClass];
[availablePlugins addObject:principalClass];
}
return availablePlugins;
}
Within each of those, a nib file is loaded upon init, which binds the root view with a property in my plugin class. Below a minimal Plugin class definition:
@interface Plugin
@property (strong) IBOutlet NSView *thePluginView;
@end
@implementation Plugin
- (instancetype)init
{
self = [super init];
if (self)
{
[NSBundle loadNibNamed:@"NibName" owner:self];
}
return self;
}
@end
While this works fine, I want to replace the above call to NSBundle (because it's deprecated for OS X 10.8+), and replace it with:
[[NSBundle mainBundle] loadNibNamed:@"NibName" owner:self topLevelObjects:nil];
However, using mainBundle in this case naturally fails to set the top level object reference in my Plugin class, I suspect cause mainBundle has nothing to do with the Plugin's bundle.
How would I go about achieving that? Is there a way to find the "current" bundle perhaps (the bundle that the Plugin class came from, so to say)?
Thanks.
回答1:
It is not clear to me exactly what you're asking - where is the "loading class" that is not in your application's bundle coming from, and what exactly do you mean by "loading class"?
Maybe the following will help:
loadNibNamed:owner:topLevelObjects:
is an instance method and loads from the bundle the instance represents.
In your sample the instance you've used you obtain via [NSBundle mainBundle]
, so the nib is loaded from the applications main bundle.
There is no "current bundle" concept, but you can obtain an NSBundle
instance representing other bundles, e.g. with NSBundle
's class method bundleWithURL
. So to load a nib from a different bundle first create an NSURL
that references the bundle, then create an NSBundle
based on that, and finally load the nib.
HTH
Addendum - After Question Updated
From the deprecated +loadNibName:owner:
method's description of owner
:
If the class of this object has an associated bundle, that bundle is searched for the specified nib file; otherwise, this method looks in the main bundle.
This is what you need to replicate when using -loadNibNamed:owner:topLevelObjects:
. The method you need is NSBundle
's bundleForClass:
which returns the NSBundle
object that dynamically loaded a class.
So in your Plugin
class you should be able to find the bundle it was loaded from with [NSBundle bundleForClass:[self class]]
and then call -loadNibNamed:owner:topLevelObjects:
on that.
来源:https://stackoverflow.com/questions/21126985/cocoa-loadnibnamedownertoplevelobjects-from-loaded-bundle