Swift 在macOS中对Apple事件使用AppleScript-脚本不起作用
我们需要使用AppleScript在macOS中创建传出电子邮件。脚本在脚本编辑器中运行良好。使用DTS推荐的代码不会产生任何结果、警告或错误。与论坛中的示例脚本结果相同。这里需要Swift和Apple Events专业知识。谢谢Swift 在macOS中对Apple事件使用AppleScript-脚本不起作用,swift,macos,applescript,macos-carbon,appleevents,Swift,Macos,Applescript,Macos Carbon,Appleevents,我们需要使用AppleScript在macOS中创建传出电子邮件。脚本在脚本编辑器中运行良好。使用DTS推荐的代码不会产生任何结果、警告或错误。与论坛中的示例脚本结果相同。这里需要Swift和Apple Events专业知识。谢谢 import Foundation import Carbon class EmailDoc: NSObject { var script: NSAppleScript = { let script = NSAppleScript(sou
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事件,以便它传递参数并调用我们刚才定义的处理程序:
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)
运行脚本,但如果您需要传递参数,则需要使用此“处理程序”方法。避免NSAppleScript
-这是一个非常重要的PITA。从ObjC/Swift访问AppleScript的最佳方法是通过,它允许您调用AppleScript处理程序,就像它们是原生ObjC methods.OMG一样!这不仅有效,还解决了我们的下一个问题,即如何将数据传递给脚本。真正的主题、接收者等。有趣的是,它是如何在0处插入所有参数的???你在几分钟内就解决了DTS花了两个多星期才回复不完整的论坛帖子的问题。最后一个问题,我们需要附加一个类中已经存在的PDF文档。使用:在最后一段之后创建属性为{file name:theAttachment}的新附件。它在脚本编辑器中运行,但不会显示在电子邮件中。有什么想法吗?再次感谢你的帮助!附件没有显示的原因只有两个:1。您在访问文件时遇到一些安全/权限问题,或2。您发送的路径说明符类型错误。脚本编辑器中的邮件附件似乎与posix路径和别名文件说明符配合使用,因此在处理程序定义中添加第五个参数(theAttachment
),并确保向其发送文本posix路径(例如,如果您在swift中有PDF的NSURL,请将theUrl.path
作为字符串说明符添加到参数列表中).我已经更新了主帖子中的示例代码。顺便说一句,“0”索引似乎是“将其添加到列表末尾”的缩写。也许是晦涩难懂,但也不太神秘……我不想再麻烦你了。但是,附件不起作用。确实找到了一个脚本,该脚本在脚本编辑器中工作正常,但无法使附件在处理程序中工作。还有一个额外的tell命令和activate命令。正在尝试发送和激活的所有组合,但无法使附件正常工作。以下是详细信息,谢谢您的帮助。不用担心。错误字典中是否有任何内容,或者在调用script.executeAppleEvent
后是否为nil?