Last active
January 25, 2020 15:38
-
-
Save marcuswestin/3bd6cfb3130cf10fcd77971073f086f0 to your computer and use it in GitHub Desktop.
Another approach for simplified wrapping of AppKit and UIKit views in SwiftUI.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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