如何从 SwiftUI 视图中 运行 AppleScript?

How to run AppleScript from inside a SwiftUI View?

我对基本的 SwiftUI 有了更多的了解,但现在我想扩展我的应用程序以实际为我做一些关于系统组件的事情。基本上我想从我的应用程序内部 运行 一个 AppleScript,它在 Mac 邮件中创建一个签名。脚本本身非常简单:

// Generates a signature in Mac Mail
tell application "Mail"
    set newSig to make new signature with properties {name:"The Signature Name"}
    set content of newSig to "My New Signature Content"
end tell

我创建了一个 view,其中包含一个应该执行脚本的按钮:

import SwiftUI

struct SomeView: View {

    @State var status = ""

    var body: some View {

        VStack(alignment: .center) {
            Button(action: {

                let source = """
                tell application \"Mail\"
                    set newSig to make new signature with properties {name: \"The Signature Name\"}
                    set content of newSig to \"My New Signature Content\"
                end tell
                """

                var error: NSDictionary?
                if let scriptObject = NSAppleScript(source: source) {
                    if let output: NSAppleEventDescriptor = scriptObject.executeAndReturnError(&error) {
                        self.status = output.stringValue ?? "some default"
                    } else if (error != nil) {
                        self.status = "error: \(error)"
                    }
                }

            }) {
                Text("Generate").font(.callout)
            }
            Text("\(self.status)")

        }
    }
}

struct SomeView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView()
    }
}

一切都执行但我收到错误

AppleScript run error = {
    NSAppleScriptErrorAppName = Mail;
    NSAppleScriptErrorBriefMessage = "Application isn\U2019t running.";
    NSAppleScriptErrorMessage = "Mail got an error: Application isn\U2019t running.";
    NSAppleScriptErrorNumber = "-600";
    NSAppleScriptErrorRange = "NSRange: {0, 0}";
}

经过一些研究,我发现 this article 很好地描述了问题。显然这个错误是 ,因为该应用程序 运行ning 在沙箱 中,而沙箱中的邮件确实不是 运行ning。我有点理解 Apple 的想法,即不让应用程序在未经用户同意的情况下为所欲为...

无论如何,不​​幸的是这篇文章描述了使用 Objective C 的解决方案,这是我比 SwiftUI 更少的线索。

谁能告诉我如何 运行 (或将我的 script.scpt 文件复制到可访问的库文件夹和 运行) SwitUI 视图中的脚本?这会很有帮助!

谢谢!!!

我已经用这种方式玩了很多,在对这个主题进行了多次讨论和试验和错误之后,我想提出 2 个解决方案 (到目前为止,这些似乎是唯一可能的沙盒应用程序的解决方案).

首先,如果您不考虑在 App Store 上发布您的应用程序,您可以忽略以下内容,因为您只需要 停用沙盒,你基本上可以自由地做任何你想做的事了!

如果您计划分发沙盒应用程序,运行在用户系统上设置脚本并与其他应用程序交互的唯一方法是运行 Application Script 文件夹中的脚本文件。此文件夹是用户库结构中指定的文件夹:/Users/thisUser/Library/Application Scripts/com.developerName.appName/。无论此处使用什么脚本,您都有权从您的应用程序 appName.

运行

您基本上有两种选择可以将您的脚本文件放入该文件夹:

选项 1 - 安装脚本文件

如果您的 脚本是静态的 (不需要您的应用程序的任何额外用户数据),这(在我看来)显然是您应该选择的选项)。您所要做的就是

  • Select项目(1)
  • 单击 构建阶段 (2)
  • 添加复制文件设置(如果还没有)
  • 在您的应用程序中选择 脚本文件位置 (通过 AppStore 分发时唱歌可能是一个不错的选择)
  • 将应用程序的 Application Script 文件夹添加到目标。因此,选择绝对路径并在路径字段中输入Users/$USER/Library/Application Scripts/$PRODUCT_BUNDLE_IDENTIFIER

如果您的脚本完全是静态的,您也可以select仅在安装时复制选项,但如果您在应用程序关闭时对脚本进行了更改并且重新打开并且您想更新脚本,请将此选项留空(我还没有测试过!)。

完成后您可以通过NSUserScriptTask执行脚本。

提供了有关如何实现此功能的更详细说明

选项 2 - 授予对文件夹的访问权限并按需复制文件

当您的 脚本文件动态更新时,这当然是解决方案 根据例如用户输入。不幸的是,这有点麻烦并且没有(在我看来)令人满意的解决方案。为此,您必须授予对文件夹的访问权限(在本例中为Application Scripts/)。这是通过 NSOpenPanel 完成的。 here.

提供了一个非常好的实现方法教程

默认情况下,您仅对该文件夹具有 读取 权限。由于您正在尝试将文件复制到该文件夹​​中,因此您还必须在 Capabilities 中将其更改为 read/write

我希望这会帮助一些人 "shine some light into the dark"!对我来说,这是一段相当长的旅程,因为那里只有很少的信息。