Примечание. Похоже, здесь существует аналогичный вопрос: Запустить вспомогательное приложение с аргументами запуска в песочнице, но я привожу более подробный пример с исходным кодом ниже.
Краткое предисловие:
Я хотел бы написать расширение редактора исходного кода Xcode (новое в Xcode 8), которое при запуске запускает сопутствующее приложение Mac, которое я пишу, и передает приложению Mac строки исходного файла, который пользователь просматривал, когда они запускали расширение .
Затем вспомогательное приложение Mac предоставит пользователю интерфейс для выполнения функций редактирования. Когда пользователь завершает свои изменения, он нажимает какую-то кнопку «Сохранить» или «Зафиксировать», и затем изменения распространяются обратно в расширение Xcode, а затем обратно в исходный исходный файл.
Что у меня есть на данный момент:
Я создал простое приложение Mac для своего вспомогательного приложения Mac. Все, что он делает в настоящее время, в его реализации applicationDidFinishLaunching(...) в его делегате приложения пытается построить строку переданных аргументов запуска и отобразить эту строку как тело сообщения предупреждения. См. ниже (обратите внимание, я пытался использовать как ProcessInfo.processInfo.arguments, так и CommandLine.arguments):
func applicationDidFinishLaunching(_ aNotification: Notification) {
let args = ProcessInfo.processInfo.arguments
var argString = ""
for arg in args {
argString += ", \(arg)"
}
let alert = NSAlert()
alert.addButton(withTitle: "OK")
alert.messageText = argString
alert.runModal()
}
Я создал довольно стандартное расширение Xcode, которое при вызове с помощью функции execute(with...) запускает вспомогательное приложение для Mac. Я пытался запустить вспомогательное приложение несколькими способами, в том числе:
Используя launchApplication NSWorkSpace(at: options: configuration:) :
class SourceEditorCommand: NSObject, XCSourceEditorCommand {
func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
defer {
completionHandler(nil)
}
guard let url = NSWorkspace.shared().urlForApplication(withBundleIdentifier: "com.something.TestMacApp") else {
print("Couldn't find URL")
return
}
let options: NSWorkspaceLaunchOptions = NSWorkspaceLaunchOptions()
var configuration: [String: Any] = [String: Any]()
configuration["foo"] = "bar"
configuration[NSWorkspaceLaunchConfigurationArguments] = ["foobar"]
configuration[NSWorkspaceLaunchConfigurationEnvironment] = ["innerFoo" : "innerBar"]
do {
try NSWorkspace.shared().launchApplication(at: url, options: options, configuration: configuration)
} catch {
print("Failed")
}
}
}
Использование пользовательского экземпляра процесса для запуска команды bash с попыткой "открыть" и "разветвить":
class SourceEditorCommand: NSObject, XCSourceEditorCommand {
func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
defer {
completionHandler(nil)
}
runCommand(command: "open -b com.something.TestMacApp --args --foo=\"bar\"")
}
func runCommand(command: String) {
let task = Process()
task.launchPath = "/bin/sh"
task.arguments = ["-c", command]
task.launch()
}
}
Проблема
Я заархивировал / экспортировал вспомогательное приложение Mac и поместил его в папку «Приложения». Когда я создаю и запускаю расширение Xcode и тестирую его, вспомогательное приложение Mac успешно запускается, но оно никогда не получает настраиваемые аргументы запуска в applicationDidFinishLaunching(...).
Я читал в нескольких местах, в том числе документацию по постоянным ключам для параметров конфигурации NSWorkSpace здесь: https://developer.apple.com/reference/appkit/nsworkspacelaunchconfigurationarguments, что «Эта константа недоступна для изолированных приложений».
Когда я запускаю тот же bash из терминала:
open -b com.something.TestMacApp --args --foo="bar"
Вспомогательное приложение успешно считывает переданные --args и отображает их в предупреждении. Я боюсь, что это просто невозможно из-за песочницы приложений, но я надеюсь, что есть другое решение, которое мне не хватает. Некоторые другие альтернативные подходы, которые также будут работать, если они возможны:
Вместо вспомогательного приложения Mac, если можно сделать так, чтобы само расширение Xcode имело интерфейс, то это решило бы проблему прямо здесь. Однако я не верю, что это возможно.
Я также мог бы запустить вспомогательное приложение Mac, а затем связаться с ним после его запуска, хотя, опять же, я думаю, что проблема с песочницей может вступить в игру.
Как бы то ни было, я в первую очередь iOS-разработчик.
Спасибо за любую помощь,
- Адам Эйсфельд