2

ScriptingBridgesの使い方を学んでいます。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

シンボルを含めることができないので、それを機能させるために何か特別なことができますか?

ありがとう、
ライアン・ペンドルトン

更新: 私は以下の1つの解決策しか見つけませんでした。それはMethodSwizzlingを含むので、私はより良い答えを受け入れることができますが、今のところ私が持っているのはそれだけです。

4

3 に答える 3

1

私が見つけた解決策は、Objective-CランタイムAPIを使用することでした。これを整理するためのより良い方法があると確信していますが、これが私がそれを行った方法です:

カテゴリを作成するための.hファイルと.mファイルは次のとおりです。lowerVolumeどのように実際のメソッドではなく、引数、、id selfおよびをもつC関数であることに注意してくださいSEL _CMDsetupCategoriesまた、関数に気付くでしょう。後で呼び出します。

// 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];
}

これのいずれかが意味をなさない場合は、私に教えてください。私はそれをよりよく説明しようとします。

于 2011-04-11T21:31:35.313 に答える
0

-framework ScriptingBridgegcc引数に含める必要があると思います。それでコンパイルできました!

于 2011-04-11T06:03:24.190 に答える
0

上記のように、コンパイル時に存在しないため、またランタイムクラス名がITunesApplication(大文字の「I」)であるため、iTunesApplicationでカテゴリを簡単に実行することはできません。

私が見つけた最善の解決策は、存在するクラス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];
}
于 2016-03-19T03:51:53.280 に答える