Skip to content

Instantly share code, notes, and snippets.

@marcuswestin
Created January 25, 2020 19:37
Show Gist options
  • Save marcuswestin/7933f5ee0dceb7be5f49ee75cc035084 to your computer and use it in GitHub Desktop.
Save marcuswestin/7933f5ee0dceb7be5f49ee75cc035084 to your computer and use it in GitHub Desktop.
An approach for simplified wrapping of AppKit and UIKit view controllers in SwiftUI
//
// WrappableViewController.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 viewControllers in SwiftUI
import SwiftUI
protocol WrappableViewController: OSViewController {
typealias ViewControllerType = Self
typealias Context = OSViewControllerRepresentableContext<WrappedViewController<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: WrappedViewController<Self> { get }
}
// MARK: Default implementations
extension WrappableViewController {
/// Default empty implementation of optional update function
func update(context: Context) {}
/// Implementation of wrapped, which should not be overriden by classes
internal var wrapped: WrappedViewController<Self> {
WrappedViewController { self }
}
}
struct WrappedViewController<Wrappable: WrappableViewController>: OSViewControllerRepresentable {
let wrap: () -> Wrappable
internal func makeCoordinator() -> Wrappable {
return wrap()
}
#if os(macOS)
internal func makeNSViewController(context: NSViewControllerRepresentableContext<WrappedViewController<Wrappable>>) -> Wrappable.ViewControllerType {
return context.coordinator
}
internal func updateNSViewController(_ view: Wrappable.ViewControllerType, context: NSViewControllerRepresentableContext<WrappedViewController<Wrappable>>) {
context.coordinator.update(context: context)
}
#elseif os(iOS)
internal func makeUIViewController(context: UIViewControllerRepresentableContext<WrapViewController>) -> Wrapper.ViewControllerType {
return context.coordinator
}
internal func updateUIViewController(_ view: Wrapper.ViewControllerType, context: UIViewControllerRepresentableContext<WrapViewController>) {
context.coordinator.update(context: context)
}
#endif
}
// MARK: - Example usage
struct WrappableViewController_Previews: PreviewProvider {
static var previews: some View {
Group {
ExampleFirstResponderTextField().wrapped
ExampleFirstResponderTextField().wrapped
}
}
final class ExampleFirstResponderTextField: NSViewController, WrappableViewController, NSTextFieldDelegate {
override func loadView() {
let textField = NSTextField(frame: .zero)
textField.stringValue = "Hello World!"
self.view = textField
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment