我只是在学习如何使用脚本桥。我制作了一种慢慢淡入iTunes上的卷的方法,并希望将其作为类别,以便我可以做以下操作:

iTunesApplication* iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
[iTunes lowerVolume:50 speed:1];

我为NSspeechSynthesizer制作了另一个类别,但我无法将其推向。我不断收到以下构建错误:

"_OBJC_CLASS_$_iTunesApplication", referenced from:
l_OBJC_$_CATEGORY_iTunesApplication_$_iTunesApplicationAdditions in iTunesApplication.o
objc-class-ref-to-iTunesApplication in iTunesApplication.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

我可以做一些特别的事情来使它起作用,因为我不能包括这些符号?

谢谢,
瑞安·彭德尔顿(Ryan Pendleton)

更新:我只找到了下面的解决方案。它涉及Methodswizzling,因此我愿意得到更好的答案,但是现在我拥有的一切。

有帮助吗?

解决方案

我发现的解决方案是使用Objective-C运行时API。我敢肯定有一种更好的组织方法,但是这就是我的做法:

这是我的.h和.m文件用于创建类别。注意如何 lowerVolume 不是实际的方法,而是具有参数的C功能 id self, , 和 SEL _CMD. 。您还会注意到 setupCategories 功能。我们稍后再说。

// iTunes+Volume.h

#import <objc/runtime.h>
#import "iTunes.h"

void lowerVolume(id self, SEL _cmd, int dest, float speed);
void setupCategories();

@interface iTunesApplication (Volume)

- (void)lowerVolume:(int)dest speed:(float)speed;

@end

// iTunes+Volume.m

#import "iTunes+Volume.h"

void lowerVolume(id self, SEL _cmd, int dest, float speed)
{
    NSLog(@"Lower Volume: %i, %f", dest, speed);
}

void setupCategories()
{
    id object = [[SBApplication alloc] initWithBundleIdentifier:@"com.apple.iTunes"];
    Class class = [object class];
    [object release];

    class_addMethod(class, @selector(lowerVolume:speed:), (IMP)lowerVolume, "@:if");
}

现在,我已经完成了功能,我需要使用Objective-C运行时API实际上将它们添加到脚本桥类中。我会做的 main.m 为了确保在运行循环启动时准备使用这些方法。

// main.m

#import <Cocoa/Cocoa.h>
#import "iTunes+Volume.h"

int main(int argc, char *argv[])
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    setupCategories();
    return NSApplicationMain(argc,  (const char **) argv);

    [pool drain];
}

现在,只要包括标头文件,我都可以在任何地方使用我的方法:

- (void)mute
{
    iTunesApplication* iTunes = [[SBApplication alloc] initWithBundleIdentifier:@"com.apple.iTunes"];
    [iTunes lowerVolume:0 speed:1];
    [iTunes release];
}

如果这没有任何意义,请告诉我,我会尝试更好地解释它。

其他提示

我认为您需要包括 -framework ScriptingBridge 对您的海湾合作委员会的论点。那为我编译了!

如上所述,您无法轻松地在iTunesapplication上进行类别,因为它在编译时不存在,而且还因为运行时类名称是iTunesapplication(Capital“ i”)。

我发现的最好的解决方案是在确实存在的类别上进行类别,即Sbapplication。这是我测试的代码可行,并执行原始示例试图做的事情:

//  SBApplication+Extensions.h

@import ScriptingBridge;

@interface SBApplication (Extensions)

- (void)lowerVolume:(int)dest speed:(float)speed;

@end

//  SBApplication+Extensions.m

#import "iTunes.h"
#import "SBApplication+Extensions.h"

@implementation SBApplication (Extensions)

- (void)lowerVolume:(int)dest speed:(float)speed
{
    NSLog(@"Lower Volume: %i, %f", dest, speed);
}

@end

// Caller, say in AppDelegate

#import "SBApplication+Extensions.h"

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{

    iTunesApplication *iTunesApp =
        [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];

    [iTunesApp lowerVolume:4 speed:3.3f];
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top