2016-10-30 18 views
1

注意:這裏看起來像一個類似的問題:Launch Helper Application with Launch Arguments in the Sandbox但我提供了一個更完整的示例與源代碼下面。Xcode Extension + Helper Mac App +啓動參數?

一個簡短的序言:

我想編寫一個Xcode源代碼編輯器擴展(在Xcode 8新)當觸發時,啓動一個伴侶的Mac應用程序我寫,並通過在Mac應用程序用戶在觸發擴展時查看的源文件行。

幫助程序Mac應用程序會爲用戶提供執行其編輯功能的界面。當用戶完成更改後,他們按下某種「保存」或「提交」按鈕,然後將更改傳回到Xcode擴展,然後回到原始源文件本身。

我有什麼至今:

我創建了一個赤裸的Mac應用程序的幫助我的Mac應用程序。它目前所做的就是在它的Application Delegate中的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的擴展,當通過執行(與調用。 ..)功能,啓動我的同伴Mac助手應用程序。我曾嘗試啓動助手應用程序幾個方面,包括:

使用NSWorkSpace的launchApplication(在:選項:配置:):

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" 

的助手應用程序successfuly讀取傳遞--args並將其顯示在警報。我的恐懼是,由於應用沙箱,這是不可能的,但我希望有另一種解決方案,我錯過了。

  1. 取而代之的是輔助性的Mac應用程序,如果有可能使Xcode的擴展本身有一個接口,那麼這將解決這個問題就在那裏:如果他們有可能也將工作的一些其他的替代方法。但我不相信這是可能的。

  2. 我也可以啓動助手的Mac應用程序,然後在啓動後與它進行通信,但我認爲也許沙盒問題可能會發揮作用。

對於它的價值,我主要是一個iOS開發人員。

感謝您的幫助,

  • 亞當Eisfeld
+0

你能完成這個(應用程序和擴展之間的雙向溝通​​)嗎?我正在嘗試實現類似的功能 - https://www.upwork.com/jobs/_~0121fceaab6de2ebcd – Crulex

回答

3

首先,你這樣做是錯誤的。正確的(如蘋果公司說,使用)的方式來啓動應用程序容器要做到以下幾點:

  1. 在容器應用程序的Info.plist中,把類似於以下(更改COM東西.cannasoftware.RoboDocument到相應的應用程序名稱和robodocument007爲字符串適合您的產品):

    enter image description here

  2. 在你的插件代碼使用以下方法來啓動應用程序:

    let customurl = NSURL.init(string: "robodocument007://") 
    NSWorkspace.shared().open(customurl as! URL) 
    
  3. 使用標準進程間通信在您的應用程序和插件之間進行聊天(DistributedNotificationCenter在此處運行良好)。

這不像使用啓動參數那麼容易或不重要,但我認爲你會對結果感到高興。

+0

雖然我同意我應該使用URL Schemes來啓動我的應用程序 - 尤其是因爲它允許其他應用程序執行此操作以標準化的方式 - 問題的核心是在應用程序打開時將某種「啓動」或「啓動」數據傳遞給應用程序。 使用DistributedNotificationCenter可能是一個解決方案,但是昨天晚上我發現我可以使用App Groups和共享的User Defaults來爲正在啓動的應用程序提供相關信息,這對我的需求來說非常合適。當我下班回家時,我會發佈一個答案來證明這一點。 –