2

注: 同様の質問がここにあるようです:サンドボックスで起動引数を使用してヘルパー アプリケーションを起動しますが、以下のソース コードでより完全な例を提供しています。

短い序文:

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()  

}  

perform(with ...) 関数を介して呼び出されると、コンパニオン Mac ヘルパー アプリを起動する、かなり定型的な Xcode 拡張機能を作成しました。次のようないくつかの方法でヘルパー アプリを起動しようとしました。

NSWorkSpace の launchApplication(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")  
        }  

    }  

}  

カスタム Process インスタンスを使用して bash コマンドを実行し、「open」と「fork」の両方を試します。

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 アプリをアーカイブ/エクスポートし、Applications フォルダーに配置しました。Xcode 拡張機能をビルドして実行し、テストすると、ヘルパー Mac アプリは正常に起動しますが、applicationDidFinishLaunching(...) でカスタム起動引数を取得しません。

ここにあるNSWorkSpace の構成オプションの定数キーのドキュメントを含む、いくつかの場所で読みました:

ターミナルから同じ bash を実行すると:

open -b com.something.TestMacApp --args --foo="bar"

ヘルパー アプリは、渡された --args を正常に読み取り、アラートに表示します。アプリのサンドボックス化が原因でこれが不可能ではないかと心配していますが、私が見逃している別の解決策があることを願っています. 可能であれば、他の代替アプローチも機能します。

  1. ヘルパー Mac アプリケーションの代わりに、Xcode 拡張機能自体にインターフェイスを持たせることができれば、問題はすぐに解決します。しかし、これが可能だとは思いません。

  2. ヘルパー Mac アプリを起動し、起動後に通信することもできますが、やはりサンドボックスの問題が発生する可能性があると思います。

なんといっても、私は主に iOS 開発者です。

助けてくれてありがとう、

  • アダム・アイスフェルド
4

1 に答える 1

4

まず、あなたはこれを間違っています。コンテナー アプリを起動する正しい (Apple が使用するように言っているように) 方法は、次のとおりです。

  1. コンテナー アプリの Info.plist に、次のような内容を入力します (com.cannasoftware.RoboDocument を適切なアプリ名に変更し、robodocument007 を製品に適した文字列に変更します)。

    ここに画像の説明を入力

  2. プラグイン コードで、次を使用してアプリを起動します。

    let customurl = NSURL.init(string: "robodocument007://")
    NSWorkspace.shared().open(customurl as! URL)
    
  3. 標準のプロセス間通信を使用して、アプリケーションとプラグインの間でチャットします (ここでは DistributedNotificationCenter が非常にうまく機能します)。

起動引数を使用するほど簡単でも些細なことでもありませんが、結果に満足できると思います。

于 2016-10-31T16:35:20.260 に答える