Macos 如何在SwiftUI视图中运行AppleScript?

Macos 如何在SwiftUI视图中运行AppleScript?,macos,applescript,swiftui,Macos,Applescript,Swiftui,我对基本的SwiftUI有了更多的了解,但现在我想扩展我的应用程序,为我做一些关于系统组件的事情。基本上,我想在我的应用程序中运行一个AppleScript,在Mac Mail中创建一个签名。脚本本身非常简单: //在Mac Mail中生成签名 告诉应用程序“邮件” 设置newSig以使用属性{name:“签名名”}创建新签名 将newSig的内容设置为“我的新签名内容” 结束语 我创建了一个带有按钮的视图,该按钮将执行脚本: 导入快捷界面 结构SomeView:View{ @状态变量stat

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

//在Mac Mail中生成签名
告诉应用程序“邮件”
设置newSig以使用属性{name:“签名名”}创建新签名
将newSig的内容设置为“我的新签名内容”
结束语
我创建了一个带有按钮的视图,该按钮将执行脚本:

导入快捷界面
结构SomeView:View{
@状态变量status=“”
var body:一些观点{
VStack(对齐:。中心){
按钮(操作:{
让source=”“”
告诉应用程序“邮件”
将newSig设置为使用属性{name:\“签名名\”}创建新签名
将newSig的内容设置为“我的新签名内容”
结束语
"""
var错误:NSDictionary?
如果let scriptObject=NSAppleScript(来源:source){
如果让输出:NSAppleEventDescriptor=scriptObject.executeAndReturnError(&error){
self.status=output.stringValue??“一些默认值”
}else if(错误!=nil){
self.status=“错误:\(错误)”
}
}
}) {
文本(“生成”).font(.callout)
}
文本(“\(self.status)”)
}
}
}
结构SomeView\u预览:PreviewProvider{
静态var预览:一些视图{
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}";
}
经过一些研究,我发现这很好地描述了这个问题。显然,这个错误是,因为应用程序正在沙箱中运行,而沙箱中的邮件确实没有运行。我有点理解苹果的想法,不让应用程序在没有用户同意的情况下做任何他们想做的事情

无论如何,不幸的是,本文使用
Objective C
描述了解决方案,而这一点我甚至没有SwiftUI那么清楚

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


谢谢

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

首先,如果你不想把你的应用程序分发到<强> AppStore ,你可以忘记下面的内容,因为你只需要“强”>去激活沙盒< /强>,你基本上可以自由地做任何你想做的事!p> 如果您计划分发沙盒应用程序,运行脚本并与用户系统上的其他应用程序交互的唯一方法是从应用程序脚本文件夹运行脚本文件。此文件夹是用户库结构中的指定文件夹:

/Users/thisUser/library/Application Scripts/com.developerName.appName/
。无论这里有什么脚本,您都有权从应用程序
appName
运行

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

选项1-安装脚本文件 在我看来,如果脚本是静态的(不需要应用程序中的任何附加用户数据),那么这显然是您应该选择的选项。你所要做的就是

  • 选择项目(1)
  • 单击构建阶段(2)
  • 添加复制文件设置(如果尚未存在)
  • 选择应用程序中的脚本文件位置(通过AppStore分发时,唱歌可能是一个不错的选择)
  • 将应用程序的
    应用程序脚本
    文件夹添加到目标。因此,选择绝对路径并在路径字段中输入
    Users/$USER/Library/Application Scripts/$PRODUCT\u BUNDLE\u IDENTIFIER
如果您的脚本是完全静态的,您还可以选择“仅在安装时复制”选项,但如果在应用程序关闭和重新打开时脚本发生了更改,并且您希望更新脚本,请将此选项保留为空(我尚未测试此项!)

完成后,您可以通过
NSUserScriptTask
执行脚本。下面将更详细地描述如何实现这一点

选项2-允许访问文件夹并按需复制文件 当您的脚本文件根据用户输入等动态更新时,这当然是解决方案。不幸的是,这有点麻烦,而且(在我看来)没有令人满意的解决方案。为此,您必须授予对该文件夹的访问权限(在本例中为
应用程序脚本/
)。这是通过
NSOpenPanel
完成的。给出了如何实现这一点的一个非常好的教程

默认情况下,您仅对该文件夹具有读取权限。由于您正试图将文件复制到该文件夹中,因此必须将其更改为在您的功能中进行读/写操作


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

链接文章在
沙盒限制
部分介绍了如何在沙盒中运行自定义脚本<不支持代码>NSAppleScript。将ObjC代码翻译成Sw并不难