我找到的解决方案是使用 Objective-C 运行时 API。我确信有更好的方法来组织它,但我是这样做的:
这是我用于创建类别的 .h 和 .m 文件。注意 howlowerVolume
不是一个实际的方法,而是一个带有参数id self
和的 C 函数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];
}
如果其中任何一个没有意义,请告诉我,我会尝试更好地解释它。