カテゴリを備えたiTunesApplicationクラスを拡張します
質問
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つしか見つかりませんでした。それには方法が必要なので、私はより良い答えを受け入れていますが、今のところそれは私が持っているすべてです。
解決
私が見つけた解決策は、Objective-C Runtime 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 Runtime 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
GCCの議論に。それは私のためにコンパイルするようにしました!
上記のように、コンパイル時に存在しないため、またランタイムクラス名がiTunesApplication(Capital "I")であるため、iTunesApplicationで簡単にカテゴリを実行することはできません。
私が見つけた最良の解決策は、存在するクラスであなたのカテゴリを行うことです。これが私がテストしたコードを機能させ、元の例がやろうとしていたことを実行しました。
// 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];
}