スクリプトオブジェクトのプロパティにラベル文字列でアクセスする、よりスマートな方法.
【実行環境】スクリプトエディタ または アプリケーションバンドル
まず前提としてある考えなのですが、レコードの項目に文字列でアクセスするために以下のコードを書きました.レコードを一度 NSDictionary オブジェクトへ変換してしまえば valueForKey: メソッドを使用して値を取り出すことができます.AppleScript の命令だけでそれを実現しようと思うと手間がかかるので、手っ取り早くそれを利用しました.
recordValueForKey01.scpt
use AppleScript version "2.5"
use framework "Foundation"
use scripting additions
set aRecord to {a:"Alphabet", b:"Balance"}
set aDict to current application's NSDictionary's dictionaryWithDictionary:aRecord
log (aDict's valueForKey:"a") as string # log (*Alphabet*)
log (aDict's valueForKey:"b") as string # log (*Balance*)
そしてこちらが本題です.上記の内容を踏まえ、同様のことをスクリプトオブジェクトに対してもできないかといろいろ試したのですが、そもそもスクリプトオブジェクトを Objective-C で扱えるオブジェクトへ変換する方法がわからず断念しました.それができれば一番良いのですが…….
そこで少し方向性を変えて「script 内に valueForKey: メソッドを実装してそれを呼び出す」コードを以下のように書きました.
scriptObjectValueForKey03.scpt
use AppleScript version "2.5" -- OS X 10.11 or later
use framework "Foundation"
use scripting additions
property NSString : a reference to current application's NSString
script aScriptObject
property a : "Alphabet"
property b : "Balance"
on valueForKey:argKey
set nKey to NSString's stringWithString:argKey
if nKey's isEqualToString:"a" then return me's a
if nKey's isEqualToString:"b" then return me's b
end valueForKey:
on setValue:argValue forKey:argKey
set nKey to NSString's stringWithString:argKey
if nKey's isEqualToString:"a" then set me's a to argValue
if nKey's isEqualToString:"b" then set me's b to argValue
end setValue:forKey:
end script
log (aScriptObject's valueForKey:"a") as string
log (aScriptObject's valueForKey:"b") as string
aScriptObject's setValue:"AppleScript" forKey:"a"
log (aScriptObject's valueForKey:"a") as string
log (aScriptObject's valueForKey:"b") as string
たしかにこの方法でも結果的に「ラベル文字列でアクセスする」ことはできたのですが、property 命令の項目が増えれば増えるだけvalueForKey: メソッド内のコードも増えますし、これは少し別件ですが、セッターメソッド(今回の場合 setValue:forKey:)も用意しようと思うと更に倍近くコードの量が増えてしまいます.けれどこれはあまりスマートな方法でないのでは? と思うのです.事実、recordValueForKey01.scpt の件で言うと、レコードの要素が増えたとしても、そのレコードの要素に対する記述が増えるだけで(例えば {a:"Alphabet", b:"Balance", c:"Copland"} )、それ以上の他のコストはかからないわけですし.
どうにかして Objective-C のメソッドを駆使して問題を解決することはできないでしょうか.どうかお知恵をお貸しください.
Mac mini, macOS 10.14