Skip to content

Instantly share code, notes, and snippets.

@marcuswestin
Last active January 25, 2020 15:38
Show Gist options
  • Save marcuswestin/3bd6cfb3130cf10fcd77971073f086f0 to your computer and use it in GitHub Desktop.
Save marcuswestin/3bd6cfb3130cf10fcd77971073f086f0 to your computer and use it in GitHub Desktop.
Another approach for simplified wrapping of AppKit and UIKit views in SwiftUI.
//
// WrappableView.swift
// macOS-Wordflower
//
// Created by Marcus Westin on 1/24/20.
// Copyright © 2020 Marcus Westin. All rights reserved.
//
// My preferred approach to wrapping AppKit and UIKit views in SwiftUI
import SwiftUI
protocol WrappableView: OSView {
typealias ViewType = Self
typealias Context = OSViewRepresentableContext<WrappedView<Self>>
/// Optional: update view
func update(context: Context)
/// Optional: wrapped has a functional default implementation and should not
/// have to be overriden by protocol implementations
var wrapped: WrappedView<Self> { get }
}
// MARK: Default implementations
extension WrappableView {
/// Default empty implementation of optional update function
func update(context: Context) {}
/// Implementation of wrapped, which should not be overriden by classes
internal var wrapped: WrappedView<Self> {
WrappedView { self }
}
}
struct WrappedView<Wrappable: WrappableView>: OSViewRepresentable {
let wrap: () -> Wrappable
internal func makeCoordinator() -> Wrappable {
return wrap()
}
#if os(macOS)
internal func makeNSView(context: NSViewRepresentableContext<WrappedView<Wrappable>>) -> Wrappable.ViewType {
return context.coordinator
}
internal func updateNSView(_ view: Wrappable.ViewType, context: NSViewRepresentableContext<WrappedView<Wrappable>>) {
context.coordinator.update(context: context)
}
#elseif os(iOS)
internal func makeUIView(context: NSViewRepresentableContext<WrapView>) -> Wrapper.ViewType {
return context.coordinator
}
internal func updateUIView(_ view: Wrapper.ViewType, context: NSViewRepresentableContext<WrapView>) {
context.coordinator.update(context: context)
}
#endif
}
// MARK: - Example usage
struct WrappableView_Previews: PreviewProvider {
static var previews: some View {
Group {
ExampleFirstResponderTextField().wrapped
ExampleFirstResponderTextField().wrapped
}
}
final class ExampleFirstResponderTextField: NSTextField, WrappableView, NSTextFieldDelegate {
override func viewDidMoveToWindow() {
DispatchQueue.main.async {
self.becomeFirstResponder()
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment