如何在 Swift MacOS 应用程序中实现 AppleScript 支持

How to implement AppleScript support in a Swift MacOS app

我正在制作一个 Swift MacOS 应用程序,它通过串行端口与外部设备交互。我可以通过该应用程序控制设备,但我希望即使在其他使用 AppleScript 的应用程序中也能控制它(我只需要 一个 简单方法,如 tell application "App" to send "string")。我搜索了大量资源,但找不到任何有用的信息。

我对 Obj-C 的了解为零。

更新:
我已经阅读了其他一些教程并且有点明白了。不幸的是,我仍然不明白如何制作 onetell application "App" to send "string" 这样简单的方法。
例如。 Spotify Mac 应用在其 .sdef 文件中包含此字符串:

    <command name="play track" code="spfyPCtx" description="Start playback of a track.">
        <access-group identifier="com.spotify.playback"/>
        <cocoa class="SPPlayTrackScriptCommand"/>
        <direct-parameter description="the URI of the track to play" type="text"/>
    </command>

他们的应用程序接收 tell application "Spotify" to play track <track> 之类的命令并执行它们。这正是我想要的。
不幸的是,我不知道他们如何在主代码中处理这个命令。也许 SPPlayTrackScriptCommand 以某种方式实现。
我已经阅读了很多教程,但仍然找不到关于这件事的任何信息。

更新#2
这就是我设法实现的目标:
Scriptable.sdef:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">

<dictionary title="App Scripting Terminology">
    
    <suite name="Scriptable App Suite" code="ScNo" description="Scriptable App suite.">
        
        <command name="send" code="SeNdtext">
            <access-group identifier="*"/>
            <direct-parameter description="Command to send" type="text" requires-access="r">
                <cocoa key="commandFlag"/>
            </direct-parameter>
            <result type="boolean" description="Did it do?"/>
        </command>
        
        <class name="application" code="capp" description="The application's basic scripting object.">
            <cocoa class="ScriptableApplication"/>
            <responds-to command="send">
                <cocoa method="send:"/>
            </responds-to>
        </class>
        
    </suite>
    
</dictionary>

ScriptableApp.swift:

@objc(ScriptableApplication) class ScriptableApplication: NSObject {
    func send(_ command: NSScriptCommand) -> Bool {
        //let commandFlag = command.evaluatedArguments?["commandFlag"] as? String
        print("A")
        return true
    }
}

测试 AppleScript:

tell application "App"
    send "string"
end tell

没有任何效果,我得到的只是缺失值

谢谢

所以,经过 4 小时的繁琐研究,我成功地完成了我想做的事情。

所有代码如下:
Scriptable.sdef:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">

<dictionary title="App Scripting Terminology">
    
    <suite name="Scriptable App Suite" code="NoSu" description="Scriptable App suite.">
        
        <command name="send" code="NoOnSend">
            <cocoa class="App.ScriptableApplicationCommand"/>
            <access-group identifier="*"/>
            <parameter code="NoCm" name="command" description="Command to send" type="text">
                <cocoa key="commandFlag"/>
            </parameter>
            <result type="text" description="ACK"/>
        </command>
        
    </suite>
    
</dictionary>

ScriptableCommand.swift:

import Foundation
import Cocoa

class ScriptableApplicationCommand: NSScriptCommand {
    override func performDefaultImplementation() -> Any? {
        let text = self.evaluatedArguments!["commandFlag"] as! String
        print(text)
        return text
    }
}

测试 AppleScript:

tell application "Noonecares"
    send command "s"
end tell

原来 App.ScriptableApplicationCommand 是必不可少的。 ScriptableApplicationCommand 一个人什么也做不了。
至少今天我学到了一些新东西。