【发布时间】:2014-08-06 14:45:19
【问题描述】:
我有一个发送电子邮件的简单 AppleScript。如何在 Swift 应用程序中调用它?
(我无法通过 Google 找到答案。)
【问题讨论】:
标签: swift applescript
我有一个发送电子邮件的简单 AppleScript。如何在 Swift 应用程序中调用它?
(我无法通过 Google 找到答案。)
【问题讨论】:
标签: swift applescript
作为Kamaros suggests,您可以直接调用NSApplescript,而无需通过NSTask(如CRGreen suggests)启动单独的进程。
Swift 代码
let myAppleScript = "..."
var error: NSDictionary?
if let scriptObject = NSAppleScript(source: myAppleScript) {
if let output: NSAppleEventDescriptor = scriptObject.executeAndReturnError(
&error) {
print(output.stringValue)
} else if (error != nil) {
print("error: \(error)")
}
}
【讨论】:
myAppleScript 时使用字符串插值。例如,如果你想在 AppleScript 中使用视图的宽度,你可以使用let myAppleScript = "set view_width to \(view.width)"
经过测试:可以做这样的事情(添加了任意脚本路径):
import Foundation
let task = Process()
task.launchPath = "/usr/bin/osascript"
task.arguments = ["~/Desktop/testscript.scpt"]
task.launch()
【讨论】:
对于收到以下 Swift 4 警告的任何人,对于从 zekel's answer 创建 NSAppleEventDescriptor 时的行
用于检查可选项的“NSAppleEventDescriptor”类型的非可选表达式
你可以用这个编辑过的短版来摆脱它:
let myAppleScript = "..."
var error: NSDictionary?
if let scriptObject = NSAppleScript(source: myAppleScript) {
if let outputString = scriptObject.executeAndReturnError(&error).stringValue {
print(outputString)
} else if (error != nil) {
print("error: ", error!)
}
}
然而,你可能也意识到了;使用这种方法,每次运行脚本时系统都会将此消息记录到控制台:
AppleEvents:收到的 mach msg 不是预期的复杂类型 在 getMemoryReference 中。
显然,这是 Apple 员工开发人员宣布的错误,据说“只是”一个无害的日志垃圾邮件,并且计划在未来的操作系统中删除更新,您可以在下面这个很长的apple developer forum post 和 SO 问题中看到:
AppleEvents: received mach msg which wasn't complex type as expected in getMemoryReference
感谢 Apple,为那些随处可见的大量垃圾控制台日志。
【讨论】:
say "Hello", but I got an error error 运行一个简单的脚本:{ NSAppleScriptErrorBriefMessage = "A \U201c/\U201d can\U2019t go here."; NSAppleScriptErrorMessage = "A \U201c/\U201d 可以\U2019t 到这里。"; NSAppleScriptErrorNumber = "-2740"; NSAppleScriptErrorRange = "NSRange: {0, 1}"; }`
您可以尝试来自 Apple 技术说明 TN2084 的 NSAppleScript 在 Cocoa 应用程序中使用 AppleScript 脚本 https://developer.apple.com/library/mac/technotes/tn2084/_index.html
NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource:
@"\
set app_path to path to me\n\
tell application \"System Events\"\n\
if \"AddLoginItem\" is not in (name of every login item) then\n\
make login item at end with properties {hidden:false, path:app_path}\n\
end if\n\
end tell"];
returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
【讨论】:
我挣扎了几个小时,但没有任何效果。最后我设法通过 shell 运行 AppleScript:
let proc = Process()
proc.launchPath = "/usr/bin/env"
proc.arguments = ["/usr/bin/osascript", "scriptPath"]
proc.launch()
不知道这是不是最好的方法,但至少它有效。
【讨论】:
env 作为shell 而不是bash 或zsh?
截至 2018 年 3 月,我认为此线程上最强的答案仍然是 accepted answer from 2011。涉及使用 NSAppleScript 或 OSAScript 的实现存在一些缺点,即存在一些轻微但非常令人不快的内存泄漏,而没有真正提供任何额外的好处。任何为正确执行该答案而苦苦挣扎的人(在 Swift 4 中)都可能想试试这个:
let manager = FileManager()
// Note that this assumes your .scpt file is located somewhere in the Documents directory
let script: URL? = try? manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
if let scriptPath = script?.appendingPathComponent("/path/to/scriptName").appendingPathExtension("scpt").path {
let process = Process()
if process.isRunning == false {
let pipe = Pipe()
process.launchPath = "/usr/bin/osascript"
process.arguments = [scriptPath]
process.standardError = pipe
process.launch()
}
}
【讨论】: