2010年1月24日日曜日

メモ: オリジナルの Automator アクションを作る

Mac OS X 10.6 では、Xcode 3.2 を使います。Mac OS X 10.6 から AppleScript Studio が deprecated になり、AppleScriptObjC を使うことになりました。簡単に言うと、AppleScript で Objective-C のクラスを書けるように、うまいこと対応を付けたものです。これによって、Automator の実行速度が上がったり、ユーザにとってはいいことずくめですが、問題は、今までの Automator アクションの作り方と大幅に変わってしまったことです。現時点では Google 先生が教えてくれる情報は、あまりアテになりません。Apple もドキュメンテーションをサボっていて、手探り状態です。

まず、知っておかないといけないのは、Xcode 3.2 が作ったテンプレートの違いです。Mac OS X 10.5 用のアクションは、以下のように、単に run ハンドラに input と parameters が渡されるだけでした。

on run {input, parameters}
  -- Add your code here, returning the data to be passed to the next action.

 return input
 
end run

これからは、myaction.script にはこんなコードが生成されます。

script myaction
 property parent : class "AMBundleAction"

 on runWithInput_fromAction_error_(input, anAction, errorRef)
  -- Add your code here, returning the data to be passed to the next action.

  return input
 end runWithInput_fromAction_error_
end script

script 〜 end script は見慣れないブロックです。これは、Objective-C のクラス定義で、myaction というクラスを宣言しています。2行目の property parent の行は AMBundleAction を継承をしていることを宣言しています。これにより、NSObject → AMActionAMAppleScriptActionAMBundleAction → myaction という継承ツリーを持ちます。on runWithInput_fromAction_error_ 〜 end runWithInput_fromAction_error_ はメソッドの定義です。オリジナルのアクションは、runWithInput:fromAction:error: をオーバーライドして作るという形になります。

AppleScript しか知らなくて、ピンと来ない人は、まずは、以下のようにテンプレートを埋めましょう。

script myaction
 property parent : class "AMBundleAction"
 
 on runWithInput_fromAction_error_(input, anAction, errorRef)
  -- Add your code here, returning the data to be passed to the next action.
  set input to input as list
  set output to {}
  repeat with i in input

   -- do something for i

  end repeat
  return output
 end runWithInput_fromAction_error_
 
end script

これで、入力ファイルに対して、順番に何かをする、という処理が書けると思います。アクションの出力は、ここではファイルと仮定しますが、POSIX File の文字列を output のリストに詰め込んで返却すれば OK です。

パラメタの参照

パラメタは以前は run ハンドラの引数に渡されていました。これからは、AMBundleAction から継承した parameters() メソッドを使って、パラメタの値が入ったレコードを取得します。個々のパラメタには AMDefaultParameters (Info.plist にあります) に設定したキーでアクセスできます。例えば、foo というキーを持つパラメタは foo of parameters() でアクセスできます。ただし、取得した値は、as text や as number などで、型をきっちり指定してください。パラメタと GUI のバインディングなどは、これまでと同じなので省略します。

アクションのバンドル

アクションのバンドルの中のファイル (リソース) の参照には path to resource は使えません。これだと Automator.app のバンドルを参照してしまいます。AMBundleAction から継承した bundle() メソッドを使って、一旦 NSBundle オブジェクトを取得したあと、NSBundle のメソッドを使ってアクセスします。名前の衝突を防ぐために、縦棒 (|) で囲って |bundle|() とやるとアクションのバンドルオブジェクトが取得できますので、それに対して、pathForResource:ofType:等を使ってリソースのパスを取得します。具体的には、以下のようになります。

set action_bundle to |bundle|()
set aPath to action_bundle's pathForResource_ofType_("image", "tiff")

エラーの返却方法などは、まだよく分かっていません。この辺になにやら書いてありますが、NSNumber と NSString を NSArray に突っ込んで返してるけど、NSError を返却するんじゃないの? という疑問が…。この情報も古いのかもしれません…。

0 件のコメント:

コメントを投稿