Apple Developer Connection
高度な検索
Member Login ログイン | ご入会 ADC連絡先

Technical Note TN2084
CocoaアプリケーションにおけるAppleScriptスクリプトの使い方

アプリケーションがCocoaを使ってObjective-Cで書かれていても、AppleScriptスクリプトを使用して一定の操作を実行できます。このテクニカルノートでは、CocoaアプリケーションをAppleScriptを組み込んで実行する方法について説明します。また、NSAppleScriptクラスを利用する方法、およびデータをレシーバに送信するNSAppleEventDescriptorの使い方についても述べます。





注: このテーマに関するCarbon開発者向けの同様のドキュメントは、テクニカルQ&AのQA1026とQA1111にあります。

要約

NSAppleScriptはアプリケーション間通信を実現する優れたツールです。また、アプリケーション内部で実行されるAppleScriptスクリプトにパラメータを渡す便利な手段です。このテクニカルノートでは、NSAppleScriptを使ってスクリプトをロード、コンパイル、実行する方法と、NSAppleEventDescriptorを使って、ロードされたスクリプトのハンドラを呼び出す方法を示します。

このテクニカルノートでは、以下の方法について説明します。

  • URLからスクリプトをロードしたり、埋め込まれたNSStringに基づいてスクリプトを作成したりする。

  • スクリプトを実行し、エラーをチェックする。

  • 実行したスクリプトまたはイベントからの応答を格納しているNSAppleEventDescriptorを取得する。

  • XcodeプロジェクトにAppleScriptを組み込む。

先頭に戻る

NSAppleScriptの作成

NSAppleScripオブジェクトのインスタンスを作成するときには、URLを使用して、テキストまたはコンパイル済み形式のスクリプトを指定できます。

NSAppleScript* appleScript = [[NSAppleScript alloc] initWithContentsOfURL:url error:&errors];

または、次のように文字列としてスクリプトを指定できます。

NSAppleScript* appleScript = [[NSAppleScript alloc] initWithSource: (NSString *)source];

スクリプトのコンパイル時または実行時にエラーが発生すると、[NSAppleScript executeAndReturnError]メソッドがエラー情報を含むディクショナリを返します。

先頭に戻る

埋め込み文字列と組み合わせてのNSAppleScriptの使用

NSAppleScriptを使用して、NSStringのインスタンスとして埋め込まれた複雑なスクリプトを実行する方法を、リスト1に示します。このコードでは、スクリプトが成功すると、返されたNSAppleEventDescriptorのインスタンスから情報を取り出しています。実行されたスクリプトが、アプリケーションを「アカウント」システム環境設定に「ログイン項目」として設定します。

リスト1: 埋め込み文字列と組み合わせてのNSAppleScriptの使用

- (IBAction)addLoginItem:(id)sender
{
    NSDictionary* errorDict;
    NSAppleEventDescriptor* returnDescriptor = NULL;

    NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource:
                @"\
                set app_path to path to me\n\
                tell application \"System Events\"\n\
                if \"AddLoginItem\" is not in (name of every login item) then\n\
                make login item at end with properties {hidden:false, path:app_path}\n\
                end if\n\
                end tell"];

    returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
    [scriptObject release];

    if (returnDescriptor != NULL)
    {
        // 実行が成功
        if (kAENullEvent != [returnDescriptor descriptorType])
        {
            // スクリプトがAppleScript結果を返す
            if (cAEList == [returnDescriptor descriptorType])
            {
                 // 結果は、他の記述子のリスト
            }
            else
            {
                // 結果を適切なObjCタイプに変換する
            }
        }
    }
    else
    {
        // スクリプト結果なし、エラーを処理
    }
}

先頭に戻る

アプリケーションバンドル内のスクリプトにおけるNSAppleScriptの使用

リスト2のコードに、アプリケーションにおいてリソースフォルダからAppleScriptスクリプトをロードし、テキストメッセージをダイアログに表示してFinderに送信する方法を示します(スクリプトはリスト3に記載します)。このコードでは、一連のNSAppleEventDescriptorsを使ってスクリプトパラメータを作成し、呼び出されるメソッド名を判断して、最終的にFinderに送信するAppleEventを作成します。

リスト2: アプリケーションバンドル内のスクリプトにおけるNSAppleScriptの使用

- (IBAction)sendFinderEvent:(id)sender
{
    // バンドル内からURLをフェッチすることで、リソースからスクリプトをロードする
    NSString* path = [[NSBundle mainBundle] pathForResource:@"SendFinderMessage" ofType:@"scpt"];
    if (path != nil)
    {
        NSURL* url = [NSURL fileURLWithPath:path];
        if (url != nil)
        {
            NSDictionary* errors = [NSDictionary dictionary];
            NSAppleScript* appleScript =
                    [[NSAppleScript alloc] initWithContentsOfURL:url error:&errors];
            if (appleScript != nil)
            {
                // 第1パラメータを作成する
                NSAppleEventDescriptor* firstParameter =
                        [NSAppleEventDescriptor descriptorWithString:@"Message from my app."];

                // パラメータのリスト(この例では1つだけ)を作成し値を設定する
                NSAppleEventDescriptor* parameters = [NSAppleEventDescriptor listDescriptor];
                [parameters insertDescriptor:firstParameter atIndex:1];

                // AppleEventターゲットを作成する
                ProcessSerialNumber psn = {0, kCurrentProcess};
                NSAppleEventDescriptor* target =
                [NSAppleEventDescriptor
                        descriptorWithDescriptorType:typeProcessSerialNumber
                        bytes:&psn
                        length:sizeof(ProcessSerialNumber)];

                // スクリプトの呼び出しメソッド名を使用してNSAppleEventDescriptorを作成する、
                // これはスクリプトステートメント「on show_message(user_message)」に使用する
                // ルーチン名は小文字にする必要がある。
                NSAppleEventDescriptor* handler =
                        [NSAppleEventDescriptor descriptorWithString:
                        [@"show_message" lowercaseString]];

                // AppleScriptサブルーチンのイベントを作成する、
                // メソッド名とパラメータリストを設定する
                NSAppleEventDescriptor* event =
                        [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite
                                eventID:kASSubroutineEvent
                                targetDescriptor:target
                                returnID:kAutoGenerateReturnID
                transactionID:kAnyTransactionID];
                [event setParamDescriptor:handler forKeyword:keyASSubroutineName];
                [event setParamDescriptor:parameters forKeyword:keyDirectObject];

                // AppleScriptのイベントを呼び出す
                if (![appleScript executeAppleEvent:event error:&errors]);
                {
                    // 'errors' からエラーを報告する
                }

                [appleScript release];
            }
            else
            {
                // 'errors' からエラーを報告する
            }
        }
    }
}

リスト3: SendFinderMessage.scptの内容

on show_message(user_message)
  tell application "Finder"
    display dialog user_message
  end tell
end show_message

重要: ソースコードとプロジェクトの管理を簡単にするために、AppleScriptスクリプトを別々のオブジェクトとして分離するほうが得策です(つまり、コンパイル済みのAppleScriptファイルをアプリケーションのリソースフォルダに分離します)。そうしておけば、ターゲットのスクリプティング環境やオブジェクトモデルが変わっても、大量のコードを変更する必要がありません。

Xcodeプロジェクトへのコンパイル済みスクリプトの組み込み

リスト2のコードはアプリケーションのResourcesフォルダからスクリプトをロードするので、Xcodeプロジェクトでは、このスクリプトを「コンパイル済みスクリプト」として用意してください。

重要: お気付きかもしれませんが、リスト3には「SendFinderMessage.scpt」というタイトルが付いています。これは「.scpt」拡張子の付いたコンパイル済みスクリプトです。スクリプトテキストファイルは「.applescrip」拡張子付きで保存されています。特にスクリプトが大きい場合は、パフォーマンスを向上させるためにコンパイル済みスクリプトをお勧めします。

Xcodeプロジェクトにスクリプトを追加するには2つの方法があります。

1. スクリプトを自分でコンパイルする

「スクリプトエディタ」を使用してスクリプトを作成・編集する場合は、テキストまたはスクリプトの2つの形式で保存できます。「スクリプト」形式は「コンパイル済みスクリプト」を意味します。コンパイル済みスクリプトとして保存する場合は、Xcodeで以下を実行します。

  • コンパイル済みスクリプト(この例では「SendFinderMessage.scpt」)をXcodeプロジェクトにドラッグします。

  • 「Copy Bundle Resources」ビルドフェーズでスクリプトファイルをインクルードします。

2. Xcodeにスクリプトをコンパイルさせる

スクリプトファイルを「テキスト」ファイルとして保存する場合は、Xcodeコードにスクリプトをコンパイルさせる必要があります。

  • スクリプトテキストファイル(この例では「SendFinderMessage.applescript」)をXcodeプロジェクトにドラッグします。

  • 新しいRun Script Build Phaseを作成し、以下を追加します(図1の例を参照)。

    osacompile -d -o SendFinderMessage.scpt SendFinderMessage.applescript

  • 新しいCopy Files Build Phaseを作成し、「SendFinderMessage.scpt」をResourcesフォルダにコピーするように設定します。

図1: Run Script Build Phase

図1 Run Script Build Phase

先頭に戻る

サンプルコード

このテクニカルノートで説明した方法を使ってCocoaアプリケーション内でAppleScriptスクリプトを使用する大規模な例を研究したい場合は、「AttachAScript」サンプルコードプロジェクトを参照してください。

先頭に戻る

オンラインドキュメント

先頭に戻る

ドキュメント改訂履歴

日付メモ
2006-09-19初版

掲載日: 2006-09-19




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.