如何允许我的 Xcode 源代码编辑器扩展使用 XPC?
How do I allow my Xcode Source Editor Extension to use XPC?
在这篇关于 Xcode 源代码编辑器扩展的文章中,它提到 XPC 是一种绕过应用程序沙箱的方法:
The extension must be sandboxed just to be loaded by Xcode, whereas calls to SourceKit needs to be un-sandboxed, which of course won’t fly in the App Store. We could distribute independently and use an un-sandboxed XPC service embedded in the extension.
但是,我不确定如何将所有内容结合在一起以使用 XPC 服务。
如何将我的 Xcode 源代码编辑器扩展绑定到 XPC 服务?
感谢 LinuxSupportForXcode extension。
我能够解决这个问题
我将假设您遵循 tutorial on creating an Xcode Extension Editor,并将主项目设为 macOS 应用程序。您的目标结构应该类似于:
- MyApp(macOS 应用目标)
- MyAppExtension(Xcode 源代码编辑器扩展目标)
将 XPC 与源代码编辑器扩展一起使用:
文件 > 新建 > 目标... > XPC 服务。
为了示例目的,我们假设它被称为 MyAppXPCService
并且它的包标识符是 com.example.MyAppXPCService
.
将XPC服务依赖从App移至Extension:
如果不执行此步骤,您可能会 运行 遇到扩展程序未执行 XPCService 的问题。例如。您调用了一个应该启动 XPCService 的命令,但是在 Xcode Debug Navigator 中,您的 XPCService 永远不会出现。
- 转到您应用的目标。
- 从框架和库中删除 MyAppXPCService.xpc。
- 转到您的扩展目标。
- 将 MyAppXPCService.xpc 添加到 Frameworks and Libraries,方法是从项目导航器的产品文件夹中将其拖入。保留默认的“不签名嵌入”。
在XPC Service中,转换为Swift,mainly following the instructions here:
注意: 如果您不想转换为 Swift,而是使用混合目标,只需创建一个 Swift 文件,然后根据提示,选择创建桥接 header,然后在桥接 header.
中包含 #import "MyAppXPCServiceProtocol.h"
正常创建main.swift
、MyService.swift
、MyServiceDelegate.swift
、MyServiceProtocol.swift
。
设置以下构建设置:
- 安装Objective-C兼容性Header:
NO
- Objective-C 生成的接口 Header 名称: ``(空白)
在构建设置中选择您想要的Swift语言版本。
在构建设置中,添加(不要替换):@loader_path/../../../../Frameworks
到运行时搜索路径.
如果您不小心替换,并使用embedded framework, XPC will crash on launch.
在您的扩展目标中:
import MyAppXPCService
以便它可以看到协议。
创建连接,使用 XPC 目标的包标识符 serviceName
:
private let connection = { () -> NSXPCConnection in
let connection = NSXPCConnection(serviceName: <#"com.example.MyAppXPCService"#>)
connection.remoteObjectInterface = NSXPCInterface(with: MyAppXPCServiceProtocol.self)
return connection
}()
调用您的 XPC 服务:
private func xpcUpperCase(input: String) {
connection.resume()
defer { connection.suspend() }
guard let xpcService = connection.remoteObjectProxy as? MyAppXPCServiceProtocol else {
throw NSError()
}
xpcService.upperCaseString(input) { output in
print(output)
}
}
创建连接的好处是它会自动启动您的 XPC 服务,而不需要 UI 应用 运行ning。
在这篇关于 Xcode 源代码编辑器扩展的文章中,它提到 XPC 是一种绕过应用程序沙箱的方法:
The extension must be sandboxed just to be loaded by Xcode, whereas calls to SourceKit needs to be un-sandboxed, which of course won’t fly in the App Store. We could distribute independently and use an un-sandboxed XPC service embedded in the extension.
但是,我不确定如何将所有内容结合在一起以使用 XPC 服务。
如何将我的 Xcode 源代码编辑器扩展绑定到 XPC 服务?
感谢 LinuxSupportForXcode extension。
我能够解决这个问题我将假设您遵循 tutorial on creating an Xcode Extension Editor,并将主项目设为 macOS 应用程序。您的目标结构应该类似于:
- MyApp(macOS 应用目标)
- MyAppExtension(Xcode 源代码编辑器扩展目标)
将 XPC 与源代码编辑器扩展一起使用:
文件 > 新建 > 目标... > XPC 服务。
为了示例目的,我们假设它被称为
MyAppXPCService
并且它的包标识符是com.example.MyAppXPCService
.将XPC服务依赖从App移至Extension:
如果不执行此步骤,您可能会 运行 遇到扩展程序未执行 XPCService 的问题。例如。您调用了一个应该启动 XPCService 的命令,但是在 Xcode Debug Navigator 中,您的 XPCService 永远不会出现。
- 转到您应用的目标。
- 从框架和库中删除 MyAppXPCService.xpc。
- 转到您的扩展目标。
- 将 MyAppXPCService.xpc 添加到 Frameworks and Libraries,方法是从项目导航器的产品文件夹中将其拖入。保留默认的“不签名嵌入”。
在XPC Service中,转换为Swift,mainly following the instructions here:
注意: 如果您不想转换为 Swift,而是使用混合目标,只需创建一个 Swift 文件,然后根据提示,选择创建桥接 header,然后在桥接 header.
中包含#import "MyAppXPCServiceProtocol.h"
正常创建
main.swift
、MyService.swift
、MyServiceDelegate.swift
、MyServiceProtocol.swift
。设置以下构建设置:
- 安装Objective-C兼容性Header:
NO
- Objective-C 生成的接口 Header 名称: ``(空白)
- 安装Objective-C兼容性Header:
在构建设置中选择您想要的Swift语言版本。
在构建设置中,添加(不要替换):
@loader_path/../../../../Frameworks
到运行时搜索路径.如果您不小心替换,并使用embedded framework, XPC will crash on launch.
在您的扩展目标中:
import MyAppXPCService
以便它可以看到协议。创建连接,使用 XPC 目标的包标识符
serviceName
:private let connection = { () -> NSXPCConnection in let connection = NSXPCConnection(serviceName: <#"com.example.MyAppXPCService"#>) connection.remoteObjectInterface = NSXPCInterface(with: MyAppXPCServiceProtocol.self) return connection }()
调用您的 XPC 服务:
private func xpcUpperCase(input: String) { connection.resume() defer { connection.suspend() } guard let xpcService = connection.remoteObjectProxy as? MyAppXPCServiceProtocol else { throw NSError() } xpcService.upperCaseString(input) { output in print(output) } }
创建连接的好处是它会自动启动您的 XPC 服务,而不需要 UI 应用 运行ning。