Какао: загрузка пакета, в котором некоторые классы наследуются от пользовательского фреймворка - PullRequest
2 голосов
/ 26 июля 2011

КРАТКАЯ ВЕРСИЯ:

Как я могу загрузить классы во время выполнения из пакета, если эти классы наследуются от суперклассов, не определенных в пакете, но от другой среды, которая была загружена ранее? При загрузке моего фреймворка содержащиеся в нем классы работают нормально. При последующей загрузке плагина все классы, которые наследуются от NSObject, работают нормально, но классы, наследуемые от платформы, не загружаются.

ДЛИТЕЛЬНАЯ ВЕРСИЯ:

Какао позволяет явно контролировать значок Dock с помощью механизма «Dock Tile Plugin». В двух словах, когда ваше приложение добавляется в Dock, ОС ищет в каталоге плагинов пакета приложения пакет с именем «MyDockTilePlugin.docktileplugin». Затем он загружает основной класс этого плагина, который должен соответствовать протоколу NSDockTilePlugIn.

Я собрал такой комплект в соответствии с руководством Apple. Теперь я хочу повторно использовать этот код, сделав классы компонентов суперклассами в моей пользовательской среде. Подклассы, специфичные для данного проекта, могут загрузить структуру.

Удивительно, но это не очень просто.

Вот процесс в psuedocode:

  • Docktileplugin загружается Dock.
  • В своем методе + initialize class класс загружает пользовательскую платформу, для которой в настройках сборки установлено значение "необязательный".
  • Затем класс загружает свой собственный плагин, который содержит классы, наследуемые от каркасных классов.
  • Что-то вроде NSLog (@ "% @", NSStringFromClass (NSClassFromString (classInheritingFromFramework)))); всегда будет отображаться (ноль)

Как наследование работает через комплекты плагинов? СПАСИБО ...

Если этой информации недостаточно, пожалуйста, попросите больше. Я стараюсь быть лаконичным и тщательным.

БОЛЬШЕ КОДА:

+ (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 ( нуль)».

Кроме того, уведомления принимаются для обоих пакетов. В платформе я вижу в ключе «NSLoadedClasses», что все классы каркаса загружены и доступны. В пакете плагинов этот список пуст (хотя в пакете должно быть несколько классов, но все они наследуются от фреймворка).

Если я добавлю третий класс к плагину, который наследуется от Какао, этот класс выглядит нормально. Кое-что о загрузке пакета классом, который наследуется от другого загруженного пакета класса, сложно. В этом суть, я думаю.

1 Ответ

1 голос
/ 30 июля 2011

Майк из http://mikeash.com - удивительный ресурс - предоставил мне совет, который решил эту проблему.Причина проблемы ускользает от меня, но она была устранена двумя действиями:

  1. В проекте Framework, установив его расположение сборки @rpath, как описано в этой статье: http://mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html
  2. В плагинах, загружающих фреймворк, слабая ссылка во время сборки, не копируйте фреймворк во время сборки, а затем установите параметр сборки -rpath для расположения фреймворка в содержащем приложении.Это гарантирует, что все элементы используют одну и ту же копию фреймворка.
...