如何从 SwiftUI 视图内部运行 AppleScript?

Flo*_*nig 5 macos applescript swiftui

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

// 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
Run Code Online (Sandbox Code Playgroud)

我创建了一个带有按钮的视图,该按钮应该执行脚本:

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

一切都执行但我收到错误

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}";
}
Run Code Online (Sandbox Code Playgroud)

经过一番研究,我发现这篇文章很好地描述了这个问题。显然这个错误是因为应用程序正在沙箱中运行,而沙箱内的邮件确实没有运行。我有点理解苹果的想法,不要让应用程序在未经用户同意的情况下为所欲为……

不管怎样,不幸的是,这篇文章描述了使用的解决方案Objective C,而我对此的了解甚至比 SwiftUI 还要少。

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

谢谢!!!

Flo*_*nig 5

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

首先,如果您不考虑在App Store上分发您的应用程序,您可以忘记以下内容,因为您只需停用沙盒,您基本上就可以自由地做任何您想做的事情!

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

基本上有两个选项可以将脚本文件放入该文件夹:

选项 1 - 安装脚本文件

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

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

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

在此输入图像描述

完成此操作后,您可以通过 执行脚本NSUserScriptTask。这里给出了如何实现这一点的更详细的描述

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

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

默认情况下,您仅拥有该文件夹的读取权限。由于您尝试将文件复制到该文件夹​​中,因此您还必须在功能中将其更改为读/写

在此输入图像描述

希望这篇文章能帮助一些人“照亮黑暗”!对我来说,这是一段相当长的旅程,因为那里的信息很少。