У меня простой AppleScript, который отправляет электронное письмо. Как я могу назвать это из приложения Swift?
(Я не смог найти ответ через Google.)
У меня простой AppleScript, который отправляет электронное письмо. Как я могу назвать это из приложения Swift?
(Я не смог найти ответ через Google.)
Не проверено, но похоже, что можно сделать что-то вроде (добавлен произвольный путь к скрипту):
import Foundation
let task = NSTask()
task.launchPath = "/usr/bin/osascript"
task.arguments = ["~/Desktop/testscript.scpt"]
task.launch()
[ОБНОВЛЕНИЕ Сейчас 2019 год, и, возможно, за последние несколько лет возник ряд проблем. Здесь обновленный код, который я только что протестировал на моей машине, которая находится на OSX Mojave 10.14.5]
ObjC.import('Foundation');
let task = $.NSTask.alloc.init;
task.launchPath = "/usr/bin/osascript";
task.arguments = ["/testing_folder/test.scpt"];
task.launch
Как предлагает Kamaros, вы можете напрямую вызвать NSApplescript без необходимости запуска отдельного процесса через NSTask (как предлагает CRGreen).
Быстрый код
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)")
}
}
Для тех, кто получает предупреждение ниже для Swift 4, для строки при создании NSAppleEventDescriptor из ответа Zekel
Необязательное выражение типа "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: получено сообщение MS Mach, которое не было сложного типа, как ожидалось в getMemoryReference.
Очевидно, это объявленная ошибка штатным разработчиком Apple, и, как говорят, это "просто" безвредный спам в журнале, который планируется удалить в будущих обновлениях ОС, как вы можете видеть в этом очень длинном сообщении на форуме разработчиков для Apple и ТАКом вопросе. ниже:
Спасибо Apple за эти миллиарды ненужных консольных журналов.
Вы можете попробовать NSAppleScript, от Apple Technical Note TN2084 Использование сценариев AppleScript в приложениях Cocoa 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];
Я боролся несколько часов, но ничего не получилось. Наконец, мне удалось запустить AppleScript через оболочку:
let proc = Process()
proc.launchPath = "/usr/bin/env"
proc.arguments = ["/usr/bin/osascript", "scriptPath"]
proc.launch()
Dunno - это лучший способ сделать это, но, по крайней мере, это работает.
По состоянию на март 2018 года, я думаю, что самый сильный ответ на эту тему по-прежнему является принятым ответом с 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()
}
}