Skip to content

Instantly share code, notes, and snippets.

@marcuswestin
Last active September 25, 2021 20:03
Show Gist options
  • Save marcuswestin/3093ed348f78aa7c1287e320a9a03072 to your computer and use it in GitHub Desktop.
Save marcuswestin/3093ed348f78aa7c1287e320a9a03072 to your computer and use it in GitHub Desktop.
An approach for simplified wrapping of AppKit and UIKit views in SwiftUI
import SwiftUI
#if os(macOS)
typealias OSView = NSView
typealias OSViewRepresentable = NSViewRepresentable
#elseif os(iOS)
typealias OSView = UIView
typealias OSViewRepresentable = UIViewRepresentable
#endif
/// Example usage:
/// ```
/// WrapView(handlers: .handlers(
/// makeView: { (context) -> NSTextField in
/// let view = NSTextField()
/// view.delegate = context.coordinator
/// return view
/// },
/// updateView: { (view, context) in
/// // ...
/// }
/// )
/// ```
struct WrapView<ViewType: OSView>: OSViewRepresentable {
typealias MakeView = (Context) -> ViewType
typealias UpdateView = (ViewType, Context) -> Void
let handlers: Handlers
init(handlers: Handlers) {
self.handlers = handlers
}
struct Handlers {
let makeView: MakeView
let updateView: UpdateView?
static func handlers(makeView: @escaping MakeView, updateView: UpdateView? = nil) -> Handlers {
return Handlers(makeView: makeView, updateView: updateView)
}
}
#if os(macOS)
func makeNSView(context: Context) -> ViewType { self.handlers.makeView(context) }
func updateNSView(_ view: ViewType, context: Context) { self.handlers.updateView?(view, context) }
#elseif os(iOS)
func makeUIView(context: Context) -> ViewType { self.handlers.makeView(context) }
func updateUIView(_ view: ViewType, context: Context) { self.handlers.updateView?(view, context) }
#endif
}
/// Example usage:
/// ```
/// WrapViewWithCoordinator(handlers: .handlers(
/// makeView: { (context) -> NSTextField in
/// let view = NSTextField()
/// view.delegate = context.coordinator
/// return view
/// },
/// updateView: { (view, context) in
/// // ...
/// },
/// makeCoordinator: {
/// Coordinator()
/// })
/// )
/// ```
struct WrapViewWithCoordinator<ViewType: OSView, Coordinator>: OSViewRepresentable {
typealias MakeView = (_ context: Context) -> ViewType
typealias UpdateView = (_ View: ViewType, _ context: Context) -> Void
typealias MakeCoordinator = () -> Coordinator
let handlers: Handlers
init(handlers: Handlers) {
self.handlers = handlers
}
struct Handlers {
let makeView: MakeView
let updateView: UpdateView
let makeCoordinator: MakeCoordinator
static func handlers(makeView: @escaping MakeView, updateView: @escaping UpdateView, makeCoordinator: @escaping MakeCoordinator) -> Handlers {
return Handlers(makeView: makeView, updateView: updateView, makeCoordinator: makeCoordinator)
}
}
#if os(macOS)
func makeNSView(context: Context) -> ViewType { self.handlers.makeView(context) }
func updateNSView(_ view: ViewType, context: Context) { self.handlers.updateView(view, context) }
func makeCoordinator() -> Coordinator { self.handlers.makeCoordinator() }
#elseif os(iOS)
func makeUIView(context: Context) -> ViewType { self.handlers.makeView(context) }
func updateUIView(_ view: ViewType, context: Context) { self.handlers.updateView(view, context) }
func makeCoordinator() -> Coordinator { self.handlers.makeCoordinator() }
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment