swift - 在 macOS 中将 AppleScript 与 Apple 事件一起使用 - 脚本不起作用
问题描述
我们需要使用 AppleScript 在 macOS 中创建外发电子邮件。该脚本在脚本编辑器中运行良好。使用 DTS https://forums.developer.apple.com/message/301006#301006推荐的代码没有结果、警告或错误。与论坛中的示例脚本结果相同。在这里需要 Swift 和 Apple Events 专业知识。谢谢!
import Foundation
import Carbon
class EmailDoc: NSObject {
var script: NSAppleScript = {
let script = NSAppleScript(source: """
set theSubject to "Some Subject"
set theContent to "Some content of the email"
set recipientName to "Some Name"
set recipientAddress to "someone@example.com"
tell application "Mail"
# Create an email
set outgoingMessage to make new outgoing message with properties {subject:theSubject, content:theContent, visible:true}
# Set the recipient
tell outgoingMessage
make new to recipient with properties {name:recipientName, address:recipientAddress}
# Send the message
send
end tell
end tell
"""
)!
let success = script.compileAndReturnError(nil)
assert(success)
return script
}()
// Script that is referenced by DTS at https://forums.developer.apple.com/message/301006#301006
// that goes with runScript method below -- runs with no results
/*var script: NSAppleScript = {
let script = NSAppleScript(source: """
on displayMessage(message)
tell application "Finder"
activate
display dialog message buttons {"OK"} default button "OK"
end tell
end displayMessage
"""
)!
let success = script.compileAndReturnError(nil)
assert(success)
return script
}() */
@objc
func runScript() {
let parameters = NSAppleEventDescriptor.list()
parameters.insert(NSAppleEventDescriptor(string: "Hello Cruel World!"), at: 0)
let event = NSAppleEventDescriptor(
eventClass: AEEventClass(kASAppleScriptSuite),
eventID: AEEventID(kASSubroutineEvent),
targetDescriptor: nil,
returnID: AEReturnID(kAutoGenerateReturnID),
transactionID: AETransactionID(kAnyTransactionID)
)
event.setDescriptor(NSAppleEventDescriptor(string: "displayMessage"), forKeyword: AEKeyword(keyASSubroutineName))
event.setDescriptor(parameters, forKeyword: AEKeyword(keyDirectObject))
var error: NSDictionary? = nil
_ = self.script.executeAppleEvent(event, error: &error) as NSAppleEventDescriptor?
print ("runScript",self.script)
}
}
解决方案
这段代码的问题——这是一个非常不明显的问题,请注意——是你正在使用旨在运行脚本处理程序(方法或子例程)的代码来尝试运行完整的脚本。Obj-C 的 AppleScript 类的奇怪之处之一是没有简单的方法来运行带参数的脚本,因此解决方法是将要执行的代码包含在脚本处理程序中,并使用调用该处理程序的 Apple 事件。为了使您的代码正常工作,您将执行以下操作...
首先,更改脚本,使代码位于处理程序中:
var script: NSAppleScript = {
let script = NSAppleScript(source: """
-- This is our handler definition
on sendMyEmail(theSubject, theContent, recipientName, recipientAddress, attachmentPath)
tell application "Mail"
-- Create an email
set outgoingMessage to make new outgoing message ¬
with properties {subject:theSubject, content:theContent, visible:true}
-- Set the recipient
tell outgoingMessage
make new to recipient ¬
with properties {name:recipientName, address:recipientAddress}
make new attachment with properties {file name:POSIX file attachmentPath}
-- Mail.app needs a moment to process the attachment, so...
delay 1
-- Send the message
send
end tell
end tell
end sendMyEmail
"""
)!
然后更改您构造的 Apple Event 以便它传递参数并调用我们刚刚定义的处理程序:
func runScript() {
let parameters = NSAppleEventDescriptor.list()
parameters.insert(NSAppleEventDescriptor(string: "Some Subject"), at: 0)
parameters.insert(NSAppleEventDescriptor(string: "Some content of the email"), at: 0)
parameters.insert(NSAppleEventDescriptor(string: "Some Name"), at: 0)
parameters.insert(NSAppleEventDescriptor(string: "someone@example.com"), at: 0)
parameters.insert(NSAppleEventDescriptor(string: attachmentFileURL.path), at: 0)
let event = NSAppleEventDescriptor(
eventClass: AEEventClass(kASAppleScriptSuite),
eventID: AEEventID(kASSubroutineEvent),
targetDescriptor: nil,
returnID: AEReturnID(kAutoGenerateReturnID),
transactionID: AETransactionID(kAnyTransactionID)
)
// this line sets the name of the target handler
event.setDescriptor(NSAppleEventDescriptor(string: "sendMyEmail"), forKeyword: AEKeyword(keyASSubroutineName))
// this line adds the parameter list we constructed above
event.setDescriptor(parameters, forKeyword: AEKeyword(keyDirectObject))
var error: NSDictionary? = nil
_ = self.script.executeAppleEvent(event, error: &error) as NSAppleEventDescriptor?
print ("runScript",self.script)
}
}
如果您不需要传递参数,您可以直接使用运行脚本script.executeAndReturnError(&error)
,但如果您需要传递参数,则需要使用这种“处理程序”方法。
推荐阅读
- elixir - 如何使用 wallaby/elixir 从 html 中检索文本?
- c# - 在 WCF 服务中更改 DataContracts 的命名空间
- java - 流口水+springboot+gradle
- ruby-on-rails - 上传带有 capistrano 'cap production deploy' 错误的 Rails 应用程序::authorize 尚未定义(ArgumentError)?
- audio - FFmpeg:如何将多个单声道文件合并为一个多声道文件?
- javascript - 如何以概率在离子中旋转轮盘游戏
- c++ - 在 C/C++ 中的 Unix 上的 PTY 伪终端上禁用 ECHO
- node.js - 树莓派上的 tfmini-plus 校验和错误
- react-native - 如何同时使用抽屉导航器和标签导航器?
- reactjs - 输入不会根据验证改变颜色 (rcc)