Macos Xcode扩展+;Helper Mac应用程序+;启动参数?

Macos Xcode扩展+;Helper Mac应用程序+;启动参数?,macos,cocoa,permissions,arguments,xcode-extension,Macos,Cocoa,Permissions,Arguments,Xcode Extension,注意:这里似乎存在一个类似的问题:但我在下面提供了一个更全面的源代码示例 简短的前言: class SourceEditorCommand: NSObject, XCSourceEditorCommand { func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {

注意:这里似乎存在一个类似的问题:但我在下面提供了一个更全面的源代码示例

简短的前言:

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")  
        }  

    }  

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

}  
我想写一个Xcode源代码编辑器扩展(在Xcode 8中是新的),当被触发时,它会启动我正在编写的配套Mac应用程序,并将用户触发扩展时正在查看的源文件的行传递给Mac应用程序

然后,helper Mac应用程序将为用户提供一个用于执行其编辑功能的界面。当用户完成更改时,他们会按某种“保存”或“提交”按钮,然后将更改传播回Xcode扩展,然后再传播回原始源文件本身

到目前为止我拥有的:

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")  
        }  

    }  

}  
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应用程序创建了一个简单的Mac应用程序。它当前所做的只是,在其应用程序委托的ApplicationIDFinishLaunching(…)实现中,尝试构建传入启动参数的字符串,并将该字符串显示为警报的消息体。请参见以下内容(注意,我已尝试使用ProcessInfo.ProcessInfo.arguments和CommandLine.arguments):

我已经创建了一个相当简单的Xcode扩展,当通过perform(with…)函数调用它时,它将启动我的配套Mac helper应用程序。我尝试了几种方式启动helper应用程序,包括:

使用NSWorkSpace的启动应用程序(在:选项:配置:):

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")  
        }  

    }  

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

}  
使用自定义流程实例运行bash命令,同时尝试“open”和“fork”:

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")  
        }  

    }  

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

}  
问题

我已存档/导出helper Mac应用程序,并将其放入应用程序文件夹中。当我构建并运行Xcode扩展并测试它时,helper Mac应用程序成功启动,但它从未在ApplicationIDFinishLaunching(…)中获得自定义启动参数

我在几个地方读过,包括NSWorkSpace配置选项的常量键文档:“此常量不适用于沙盒应用程序。”

当我从终端运行相同的bash时:

open -b com.something.TestMacApp --args --foo="bar"
helper应用程序成功读入传递的--args并在警报中显示它们。我担心这根本不可能,因为应用程序沙箱,但我希望有另一个解决方案,我错过了。如果可能的话,其他一些替代方法也会起作用:

  • 如果可以让Xcode扩展本身有一个接口,而不是一个helper Mac应用程序,那么这就解决了问题。然而,我认为这是不可能的

  • 我也可以启动helper Mac应用程序,然后在它启动后与它进行通信,尽管我再次认为沙箱问题可能会起作用

  • 无论如何,我主要是一名iOS开发人员

    谢谢你的帮助

    • 亚当·艾斯菲尔德

      • 首先,你做错了。启动container应用程序的正确方式(正如苹果所说的那样)是执行以下操作:

      • 在容器应用程序的Info.plist中,放置类似于以下内容的内容(将com.cannasoftware.RoboDocument更改为适当的应用程序名称,将robodocument007更改为适合您的产品的字符串):

      • 在您的插件代码中,使用以下命令启动应用程序:

        let customurl = NSURL.init(string: "robodocument007://")
        NSWorkspace.shared().open(customurl as! URL)
        
      • 使用标准进程间通信在应用程序和插件之间聊天(DistributedNotificationCenter在这里工作得很好)


      • 这不像使用启动参数那么简单或琐碎,但我认为你会对结果感到高兴。

        虽然我同意我应该使用URL方案来启动我的应用程序,特别是因为它允许其他应用程序以标准化的方式启动,但问题的核心是传递某种“启动”或“发射“当应用程序打开时,将数据发送到应用程序。使用DistributedNotificationCenter可能是一种解决方案,但是昨晚我发现我可以使用应用程序组和共享用户默认值为正在启动的应用程序提供相关信息,这非常适合我的需要。我下班回家后会发布一个答案来证明这一点。@AdamEisfeld,我很想看看你的应用程序组解决方案!介意把它贴出来吗?我猜它没有他想象的那么好。有时候,不管你想要什么,遵循苹果禁止的文档工作得更好,痛苦更少。你能完成这个(应用程序和扩展之间的双向通信)吗?我正在努力实现类似的目标-