AppleScript编译与解释执行时枚举属性输出差异问题咨询
我写的这段AppleScript代码:
on collectionToJson(_collection) tell application "Capture One 22" to return "{\"name\": " & "\"" & name of _collection & "\", \"id\": " & id of _collection & ", \"kind\": " & "\"" & kind of _collection & "\", \"user\": " & user of _collection & "}" end collectionToJson
在解释执行和编译执行时输出结果不一致:
解释执行(直接运行.applescript源文件):
> osascript target/classes/Collections.applescript --byId 14659 {"name": "StoppingDown", "id": 14659, "kind": "project", "user": true}
编译执行(运行编译后的.scpt文件):
> osascript target/classes/Collections.scpt --byId 14659 {"name": "StoppingDown", "id": 14659, "kind": "«constant ****CCpj»", "user": true}
可以看到,作为枚举类型的kind属性输出形式有明显差异:解释执行时输出可读字符串"project",编译执行时却变成了内部常量标识«constant ****CCpj»。
请问这种差异是因为我对AppleScript的理解有误,还是和交互的Capture One 22应用有关?
完整脚本如下:
on run (_args) tell front document of application "Capture One 22" set _command to item 1 of _args if _command is "--byId" then set _collection to my findCollectionByIdPath(_args) my collectionToJson(_collection) else if _command is "--byName" then set _collection to collection named (item 2 of _args) repeat with _i from 3 to count of _args tell _collection to set _collection to collection named (item _i of _args) end repeat my collectionToJson(_collection) else if _command is "--children" then set _collection to my findCollectionByIdPath(_args) tell _collection to my collectionsToJson(collections) else if _command is "--variants" then set _collection to my findCollectionByIdPath(_args) tell _collection to my variantsToJson(variants) else log "Unknown command: " & _command end if end tell end run on findCollectionByIdPath(_args) tell front document of application "Capture One 22" set _collection to first collection whose its id is item 2 of _args repeat with _i from 3 to count of _args tell _collection to set _collection to (first collection whose its id is (item _i of _args)) end repeat return _collection end tell end findCollectionByIdPath on collectionsToJson(_collections) set _result to "[" set _separator to "" repeat with _collection in _collections set _result to _result & _separator & my collectionToJson(_collection) set _separator to "," end repeat return _result & "]" end collectionsToJson on collectionToJson(_collection) tell application "Capture One 22" to return "{\"name\": " & "\"" & name of _collection & "\", \"id\": \"" & id of _collection & "\", \"kind\": " & "\"" & kind of _collection & "\", \"user\": " & user of _collection & "}" end collectionToJson on variantsToJson(_variants) set _result to "[" set _separator to "" repeat with _variant in _variants set _result to _result & _separator & my variantToJson(_variant) set _separator to "," end repeat return _result & "]" end variantsToJson on variantToJson(_variant) -- FIXME: it seems that this 'tell' slows down a lot tell application "Capture One 22" to return ("{\"name\": \"" & (name of _variant) as text) & "\", \"id\": \"" & id of _variant & "\", \"rating\": " & rating of _variant & ", \"colorTag\": " & color tag of _variant & "}" end variantToJson
问题原因分析
这种差异是AppleScript编译机制与Capture One 22脚本字典实现共同作用的结果:
解释执行的行为:直接运行
.applescript源文件时,AppleScript解释器会实时查询Capture One 22的脚本字典,将枚举类型的内部常量(如«constant ****CCpj»)动态转换为对应的可读字符串(如"project")。编译执行的行为:编译成
.scpt文件时,AppleScript编译器会将枚举值替换为对应的内部常量标识,而非保留可读名称。这是为了提升执行效率,编译后的脚本会存储应用定义的常量内部ID,不再依赖运行时的字典查询,但代价是无法自动转换为可读名称。Capture One的影响:不同应用对AppleScript枚举的实现存在差异,部分应用会确保编译后的脚本仍能解析枚举的可读名称,但Capture One 22的脚本字典处理方式导致编译后只能输出内部常量标识。
解决方法
要让两种执行方式都输出可读的kind字符串,可以手动建立内部常量与可读名称的映射:
on getCollectionKindName(_kindConstant) -- 根据Capture One实际枚举值补充完整映射 set kindMap to {«constant ****CCpj»:"project", «constant ****CCpt»:"album", «constant ****CCpf»:"folder"} if _kindConstant is in kindMap then return kindMap's item _kindConstant else return "unknown" end if end getCollectionKindName
修改collectionToJson函数,调用上述映射函数:
on collectionToJson(_collection) tell application "Capture One 22" set kindName to my getCollectionKindName(kind of _collection) return "{\"name\": \"" & name of _collection & "\", \"id\": \"" & id of _collection & "\", \"kind\": \"" & kindName & "\", \"user\": " & user of _collection & "}" end tell end collectionToJson
内容的提问来源于stack exchange,提问作者Fabrizio Giudici

