Skip to content

Instantly share code, notes, and snippets.

@maximkrouk
Last active October 23, 2024 09:38
Show Gist options
  • Save maximkrouk/d38f9ec9ffa9fad4a30e87fab29298ed to your computer and use it in GitHub Desktop.
Save maximkrouk/d38f9ec9ffa9fad4a30e87fab29298ed to your computer and use it in GitHub Desktop.
SwiftUI adapter for AppKit/UIKit views/view controllers
import SwiftUI
public struct Component<Target, Coordinator, Body: View>: View {
private var makeBody: () -> Body
public var body: Body { makeBody() }
}
#if os(macOS)
public struct _ViewBody<Target: NSView, Coordinator>: NSViewRepresentable {
internal var _makeTarget: (Context) -> Target
internal var _updateTarget: (Target, Context) -> Void
internal var _makeCoordinator: () -> Coordinator
public func makeNSView(context: Context) -> Target {
_makeTarget(context)
}
public func updateNSView(_ nsView: Target, context: Context) {
_updateTarget(nsView, context)
}
public func makeCoordinator() -> Coordinator {
_makeCoordinator()
}
}
public struct _ViewControllerBody<Target: NSViewController, Coordinator>: NSViewControllerRepresentable {
internal var _makeTarget: (Context) -> Target
internal var _updateTarget: (Target, Context) -> Void
internal var _makeCoordinator: () -> Coordinator
public func makeNSViewController(context: Context) -> Target {
_makeTarget(context)
}
public func updateNSViewController(_ nsViewController: Target, context: Context) {
_updateTarget(nsViewController, context)
}
public func makeCoordinator() -> Coordinator {
_makeCoordinator()
}
}
extension Component
where Target: NSView, Body == _ViewBody<Target, Coordinator> {
public init(target: @escaping (Body.Context) -> Target,
coorinator: @escaping () -> Coordinator,
onUpdate:((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: target,
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: coorinator
)
}
}
public init(target: @escaping () -> Target,
coorinator: @escaping () -> Coordinator,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
self.init(
target: { _ in target() },
coorinator: coorinator,
onUpdate: onUpdate
)
}
public init(target: @escaping () -> Target,
coorinator: @escaping @autoclosure () -> Coordinator,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
self.init(
target: target,
coorinator: coorinator,
onUpdate: onUpdate
)
}
public init(_ target: @escaping @autoclosure () -> Target,
coorinator: @escaping () -> Coordinator,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
self.init(
target: target,
coorinator: coorinator,
onUpdate: onUpdate
)
}
public init(_ target: @escaping @autoclosure () -> Target,
coorinator: @escaping @autoclosure () -> Coordinator,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
self.init(
target: target,
coorinator: coorinator,
onUpdate: onUpdate
)
}
}
extension Component
where Target: NSView, Coordinator == Void, Body == _ViewBody<Target, Coordinator> {
public init(target: @escaping (Body.Context) -> Target,
onUpdate:((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: target,
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: { () }
)
}
}
public init(target: @escaping () -> Target,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
self.init(
target: { _ in target() },
onUpdate: onUpdate
)
}
public init(_ target: @escaping @autoclosure () -> Target,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
self.init(
target: target,
onUpdate: onUpdate
)
}
}
extension Component
where Target: NSViewController, Body == _ViewControllerBody<Target, Coordinator> {
public init(target: @escaping (Body.Context) -> Target,
coorinator: @escaping () -> Coordinator,
onUpdate:((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: target,
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: coorinator
)
}
}
public init(_ target: @escaping @autoclosure () -> Target,
coorinator: @escaping @autoclosure () -> Coordinator,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: { _ in target() },
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: coorinator
)
}
}
}
extension Component
where Target: NSViewController, Coordinator == Void, Body == _ViewControllerBody<Target, Coordinator> {
public init(target: @escaping (Body.Context) -> Target,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: target,
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: { () }
)
}
}
public init(_ target: @escaping @autoclosure () -> Target,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: { _ in target() },
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: { () }
)
}
}
}
#elseif os(iOS)
public struct _ViewBody<Target: UIView, Coordinator>: UIViewRepresentable {
internal var _makeTarget: (Context) -> Target
internal var _updateTarget: (Target, Context) -> Void
internal var _makeCoordinator: () -> Coordinator
public func makeUIView(context: Context) -> Target {
_makeTarget(context)
}
public func updateUIView(_ uiView: Target, context: Context) {
_updateTarget(uiView, context)
}
public func makeCoordinator() -> Coordinator {
_makeCoordinator()
}
}
public struct _ViewControllerBody<Target: UIViewController, Coordinator>: UIViewControllerRepresentable {
internal var _makeTarget: (Context) -> Target
internal var _updateTarget: (Target, Context) -> Void
internal var _makeCoordinator: () -> Coordinator
public func makeUIViewController(context: Context) -> Target {
_makeTarget(context)
}
public func updateUIViewController(_ uiViewController: Target, context: Context) {
_updateTarget(uiViewController, context)
}
public func makeCoordinator() -> Coordinator {
_makeCoordinator()
}
}
extension Component
where Target: UIView, Body == _ViewBody<Target, Coordinator> {
public init(target: @escaping (Body.Context) -> Target,
coorinator: @escaping () -> Coordinator,
onUpdate:((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: target,
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: coorinator
)
}
}
public init(_ target: @escaping @autoclosure () -> Target,
coorinator: @escaping @autoclosure () -> Coordinator,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: { _ in target() },
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: coorinator
)
}
}
}
extension Component
where Target: UIView, Coordinator == Void, Body == _ViewBody<Target, Coordinator> {
public init(target: @escaping (Body.Context) -> Target,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: target,
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: { () }
)
}
}
public init(_ target: @escaping @autoclosure () -> Target,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: { _ in target() },
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: { () }
)
}
}
}
extension Component
where Target: UIViewController, Body == _ViewControllerBody<Target, Coordinator> {
public init(target: @escaping (Body.Context) -> Target,
coorinator: @escaping () -> Coordinator,
onUpdate:((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: target,
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: coorinator
)
}
}
public init(_ target: @escaping @autoclosure () -> Target,
coorinator: @escaping @autoclosure () -> Coordinator,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: { _ in target() },
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: coorinator
)
}
}
}
extension Component
where Target: UIViewController, Coordinator == Void, Body == _ViewControllerBody<Target, Coordinator> {
public init(target: @escaping (Body.Context) -> Target,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: target,
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: { () }
)
}
}
public init(_ target: @escaping @autoclosure () -> Target,
onUpdate: ((Target, Body.Context) -> Void)? = .none) {
makeBody = {
Body(
_makeTarget: { _ in target() },
_updateTarget: onUpdate ?? { _, _ in },
_makeCoordinator: { () }
)
}
}
}
#endif
@maximkrouk
Copy link
Author

maximkrouk commented Mar 18, 2020

Usage

import SwiftUI
import MapKit

struct Example: View {
    var body: some View {
         Component(MKMapView()) // wrap any UIView (or NSView)
    }
}

struct VCExample: View {
    var body: some View {
         Component(SomeViewController()) // wrap any UIViewController (or NSViewController)
    }
}

Back to index

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment