Swiftpack.co - ChimeHQ/Extendable as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by ChimeHQ.
ChimeHQ/Extendable 0.2.0
A set of utilities for more pleasant work with ExtensionKit
⭐️ 38
🕓 24 weeks ago
iOS macOS watchOS tvOS
.package(url: "https://github.com/ChimeHQ/Extendable.git", from: "0.2.0")

Build Status Platforms Documentation

Extendable

A set of utilities for more pleasant work with ExtensionKit

Installation

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")]
    ),
]

Global Connection

Setting up an ExtensionKit extension can be confusing, and requires a fair amount of boilerplate. ConnectableExtension makes it easier to manage the global host connection.

@main
final class ExampleExtension: ConnectableExtension {
    init() {
    }

    func acceptConnection(_ connection: NSXPCConnection) throws {
        // configure your global connection and possibly
        // store references to host interface objects
    }
}

Scenes

Dealing with View-based extensions is even more complex. And, there isn't a clear way to get access to the host connection in your views. Extendable comes with a few components that make it easier to build scenes and manage view connections.

ConnectingAppExtensionScene

This is a AppExtensionScene that makes it easier to get access to the scene's connection within your View.

ConnectingAppExtensionScene(sceneID: "one") { (sceneId, connection) in
    try ConnectionView(sceneId: sceneId, connection: connection)
}

AppExtensionSceneGroup

I expect this type won't be needed once Ventura ships. And, maybe it's just me, but I've been unable to figure out how to use AppExtensionSceneBuilder without a wrapper type. So here it is.

Example View

You can use ConnectingAppExtensionScene and AppExtensionSceneGroup independently, or as part of a more standard extension structure. But, if you want, you can also make use of the ConnectableSceneExtension protocol to really streamline your view class. Here's a full example:

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

ExtendableHost

Extendable also includes a second library called ExtendableHost.

You can its AppExtensionBrowserView and ExtensionHostingView to integrate the ExtensionKit view system with SwiftUI in your host application.

// very simple init extension to help with actor-isolation compatibility
let process = try await AppExtensionProcess(appExtensionIdentity: identity)

Contributing and Collaboration

I'd love to hear from you! Get in touch via an issue or pull request.

I prefer collaboration, and would love to find ways to work together if you have a similar project.

I prefer indentation with tabs for improved accessibility. But, I'd rather you use the system you want and make a PR than hesitate because of whitespace.

By participating in this project you agree to abide by the Contributor Code of Conduct.

GitHub

link
Stars: 38
Last commit: 5 days ago
jonrohan Something's broken? Yell at me @ptrpavlik. Praise and feedback (and money) is also welcome.

Release Notes

v0.2.0
24 weeks ago
  • renames the host-side library to ExtendableHost to be less-specific about just views
  • adds a small convenience init method to AppExtensionProcess to help with Sendability

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics