Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c Cocoa:加载一个包,其中一些类从自定义框架继承_Objective C_Cocoa_Plugins - Fatal编程技术网

Objective c Cocoa:加载一个包,其中一些类从自定义框架继承

Objective c Cocoa:加载一个包,其中一些类从自定义框架继承,objective-c,cocoa,plugins,Objective C,Cocoa,Plugins,简短版本: 当这些类继承自捆绑包中未定义的超类,但来自之前加载的另一个框架时,如何在运行时从捆绑包加载类?加载我的框架时,其中包含的类工作正常。之后加载插件时,从NSObject继承的任何类都可以正常工作,但不会加载从框架继承的类 长版本: Cocoa允许您通过“Dock Tile插件”机制显式控制Dock图标。简而言之,当你的应用程序被添加到Dock中时,操作系统会在应用程序的bundle plugins目录中查找一个名为“MyDockTilePlugin.docktileplugin”的bu

简短版本:

当这些类继承自捆绑包中未定义的超类,但来自之前加载的另一个框架时,如何在运行时从捆绑包加载类?加载我的框架时,其中包含的类工作正常。之后加载插件时,从NSObject继承的任何类都可以正常工作,但不会加载从框架继承的类

长版本:

Cocoa允许您通过“Dock Tile插件”机制显式控制Dock图标。简而言之,当你的应用程序被添加到Dock中时,操作系统会在应用程序的bundle plugins目录中查找一个名为“MyDockTilePlugin.docktileplugin”的bundle。然后加载该插件的主要类,该类必须符合NSDockTilePlugIn协议

根据苹果的指南,我已经建立了这样一个捆绑包。现在,我想通过在自定义框架中使组件类成为超类来重用这段代码。特定于给定项目的子类可以加载框架

令人惊讶的是,这并不十分简单

以下是psuedocode中的流程:

  • docktileplugin由Dock加载
  • 在其+initialize类方法中,该类加载自定义框架,该框架在构建设置中设置为“可选”
  • 然后类加载自己的插件,该插件包含从框架类继承的类
  • 类似于NSLog(@“%@”、NSStringFromClass(NSClassFromString(ClassInWritingFromFramework));将始终显示(空)
继承如何跨插件包工作?谢谢

如果这还不够,请询问更多信息。我尽量做到简洁透彻

更多代码:

+ (void)initialize {
[[NSNotificationCenter defaultCenter] addObserverForName:NSBundleDidLoadNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
    NSLog(@"bundle loaded %@", note);
}];

//Plugin bundle
NSBundle *selfBundle = [NSBundle bundleForClass:[self class]];

//Load Custom Framework
NSString *frameworkName = @"Custom.framwork";
NSString *frameworkPath = [[selfBundle bundlePath] stringByAppendingPathComponent:[@"Contents/Frameworks" stringByAppendingPathComponent:frameworkName]];
NSLog(@"Framework %@ at %@", ([[NSFileManager defaultManager] fileExistsAtPath:frameworkPath]? @"EXISTS" : @"DOES NOT EXISTS"), frameworkPath);
if( [[NSBundle bundleWithPath:frameworkPath] load] ) {
    NSLog(@"Framework loaded...");
    NSLog(@"Framework provided classes such as DockTilePlugin (%@) and UndoManager (%@)", NSStringFromClass(NSClassFromString(@"DockTilePlugin")), NSStringFromClass(NSClassFromString(@"UndoManager")));
} else {
    NSLog(@"Error, framework failed to load.");
    exit(1);
}   

//Load Dock Tile Plugin
NSString *pluginName = [[selfBundle infoDictionary] objectForKey:@"DockTilePluginCoreBundle"];
NSString *pluginPath = [[selfBundle builtInPlugInsPath] stringByAppendingPathComponent:[pluginName stringByAppendingPathExtension:@"bundle"]];
NSLog(@"Plugin %@ at %@", ([[NSFileManager defaultManager] fileExistsAtPath:pluginPath]? @"EXISTS" : @"DOES NOT EXISTS"), pluginPath);
if( [[NSBundle bundleWithPath:pluginPath] load] ) {
    NSLog(@"Plugin loaded...");
    NSLog(@"Plugin provided classes such as DockTilePlugin (%@) and DockTileView (%@)", NSStringFromClass(NSClassFromString(@"DockTilePlugin")), NSStringFromClass(NSClassFromString(@"DockTileView")));
} else {
    NSLog(@"Error, Plugin failed to load.");
    exit(1);
}   
}
我在Console.app中看到的输出是前两个“类,例如”显示(类名称出现),但在后两个中,我得到了“插件提供的类,例如DockTilePlugin(null)和DockTileView(null)”

此外,两个bundle都会收到通知。在框架中,我在“NSLoadedClasses”键中看到所有框架类都已加载且可用。在插件包中,这个列表是空的(虽然包中应该有几个类,但它们都是从框架继承的)

如果我在插件中添加第三个类(继承自Cocoa),该类看起来很好。关于bundle加载一个从另一个bundle加载的类继承的类是很棘手的。我想这就是问题的核心所在。

Mike from——一个了不起的资源——为我提供了解决这个问题的技巧。我无法找到问题的原因,但通过做两件事解决了问题:

  • 在框架的项目中,将其构建位置设置为@rpath,如本文所述:
  • 在加载框架的插件中,在构建期间弱引用,在构建期间不复制框架,然后将-rpath构建设置设置为框架在包含应用程序中的位置。这确保所有项目都使用相同的框架副本

  • 您可以发布
    +initialize
    方法的代码吗?