一套用于更轻松地使用 ExtensionKit 的实用工具集
dependencies: [
.package(url: "https://github.com/ChimeHQ/Extendable", from: "0.1.0")
],
targets: [
.target(
name: "ExtensionSide",
dependencies: ["Extendable"]
),
.target(
name: "HostSide",
dependencies: [.product(name: "ExtendableHost", package: "Extendable")]
),
]
设置 ExtensionKit 扩展可能令人困惑,并且需要大量的样板代码。ConnectableExtension
使管理全局主机连接更容易。
@main
final class ExampleExtension: ConnectableExtension {
init() {
}
func acceptConnection(_ connection: NSXPCConnection) throws {
// configure your global connection and possibly
// store references to host interface objects
}
}
处理基于 View 的扩展更加复杂。而且,没有明确的方法可以在您的视图中访问主机连接。 Extendable 提供了一些组件,可以更轻松地构建场景和管理视图连接。
这是一个 AppExtensionScene
,可以更容易地在您的 View
中访问场景的连接。
ConnectingAppExtensionScene(sceneID: "one") { (sceneId, connection) in
try ConnectionView(sceneId: sceneId, connection: connection)
}
我预计 Ventura 发布后,这种类型将不再需要。而且,也许只是我个人观点,但我一直无法弄清楚如何在没有包装类型的情况下使用 AppExtensionSceneBuilder
。 所以它就在这里。
您可以独立使用 ConnectingAppExtensionScene
和 AppExtensionSceneGroup
,或者作为更标准扩展结构的一部分。 但是,如果您愿意,您也可以使用 ConnectableSceneExtension
协议来真正简化您的视图类。 这是一个完整的例子
@main
final class ViewExtension: ConnectableSceneExtension {
init() {
}
func acceptConnection(_ connection: NSXPCConnection) throws {
// handle global connection
}
var scene: some AppExtensionScene {
AppExtensionSceneGroup {
ConnectingAppExtensionScene(sceneID: "one") { (sceneId, connection) in
try ConnectionView(sceneId: sceneId, connection: connection)
}
ConnectingAppExtensionScene(sceneID: "two") { (sceneId, connection) in
try ConnectionView(sceneId: sceneId, connection: connection)
}
}
}
}
struct ConnectionView: View {
let sceneName: String
let connection: NSXPCConnection?
init(sceneId: String, connection: NSXPCConnection?) throws {
self.sceneName = sceneId
self.connection = connection
}
var value: String {
return String(describing: connection)
}
var body: some View {
VStack {
Rectangle().frame(width: nil, height: 4).foregroundColor(.green)
Spacer()
Text("\(sceneName): \(value)")
Spacer()
Rectangle().frame(width: nil, height: 4).foregroundColor(.red)
}
}
}
Extendable 还包括一个名为 ExtendableHost
的第二个库。
您可以使用它的 AppExtensionBrowserView
和 ExtensionHostingView
,将 ExtensionKit 视图系统与您主机应用程序中的 SwiftUI 集成。
// very simple init extension to help with actor-isolation compatibility
let process = try await AppExtensionProcess(appExtensionIdentity: identity)
目前,AppExtention
协议中的 init
缺乏任何隔离。 如果您依赖扩展的真实但未表达的 @MainActor
隔离,这将使初始化实例变量变得困难。 我包含了一个可以提供帮助的解决方法。 SE-0414 将使这不再必要,ExtensionFoundation 添加注释也会如此。 但与此同时,没有警告是件好事。
@main
final class MyExtension: AppExtension {
@InitializerTransferred private var value: MainActorType
nonisolated init() {
self._value = InitializerTransferred(mainActorProvider: {
MainActorType()
})
}
}
我很乐意收到你的来信! Issues 或 pull requests 都很棒。 Matrix 空间 也可用于实时帮助,但我强烈倾向于以文档的形式回答。
我更喜欢协作,如果您有类似的项目,我很乐意找到合作的方式。
我更喜欢使用制表符进行缩进,以提高可访问性。 但是,我宁愿你使用你想要的系统并创建一个 PR,而不是因为空格而犹豫不决。
参与此项目即表示您同意遵守 贡献者行为准则。