Cyborg/SwiftUIView.swift (91 lines of code) (raw):

// // Copyright (c) 2019. Uber Technologies // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #if canImport(SwiftUI) import SwiftUI /// A `VectorDrawableView` for SwiftUI. /// /// # Experimental /// This feature is experimental and may change. /// Current areas where this API may be deficient are: /// /// 1. The drawable must be fully parsed before the view's init is called, which isn't in the spirit of SwiftUI's views being /// cheap to construct. /// /// 2. Handling of resources is a bit hacky. See below for details. /// /// 3. Further testing of how the view handles sizing is required. /// /// # Usage /// /// You initialize a `VectorDrawableView` with /// `init(_ drawable:)`. /// /// You can provide the `theme` and `resources` through /// `environment()`. It seems as though `theme` is better suited to be an `EnvironmentObject` than /// merely part of the `Environment`, but there doesn't seem to be any way to access an `EnvironmentObject` inside of /// `updateUIView` without crashing. If you want dynamic theme changes, the easiest way currently is to bind an `EnvironmentObject` /// higher in your view hierarchy, then use its output to mutate the `Environment` by calling `View.environment` on the child /// tree that contains the drawables you want to theme. /// /// - Note: `resources` does not update after the view is first created, /// it's passed as an `Environment` var solely for convenience. @available(iOS 13.0, OSX 10.15, tvOS 13.0, *) public struct VectorDrawableView { public let drawable: VectorDrawable /// Initializer. public init(_ drawable: VectorDrawable) { self.drawable = drawable } } #if os(macOS) @available(OSX 10.15, *) extension VectorDrawableView: NSViewRepresentable { public typealias NSViewType = VectorView public func makeNSView(context: NSViewRepresentableContext<VectorDrawableView>) -> VectorView { let view = VectorView(theme: context.environment.vectorDrawableTheme, resources: context.environment.vectorDrawableResources) view.setContentHuggingPriority(.defaultHigh, for: .horizontal) view.setContentHuggingPriority(.defaultHigh, for: .vertical) view.drawable = drawable return view } public func updateNSView(_ uiView: VectorView, context: NSViewRepresentableContext<VectorDrawableView>) { uiView.drawable = drawable uiView.theme = context.environment.vectorDrawableTheme } } #else @available(iOS 13.0, tvOS 13.0, *) extension VectorDrawableView: UIViewRepresentable { public func makeUIView(context: UIViewRepresentableContext<VectorDrawableView>) -> VectorView { let view = VectorView(theme: context.environment.vectorDrawableTheme, resources: context.environment.vectorDrawableResources) view.setContentHuggingPriority(.defaultHigh, for: .horizontal) view.setContentHuggingPriority(.defaultHigh, for: .vertical) view.drawable = drawable return view } public func updateUIView(_ uiView: VectorView, context: UIViewRepresentableContext<VectorDrawableView>) { uiView.drawable = drawable uiView.theme = context.environment.vectorDrawableTheme } } #endif /// The key for Vector Drawable themes. public struct ThemeKey: EnvironmentKey { public static let defaultValue: ThemeProviding = { struct DefaultTheme: ThemeProviding { func colorFromTheme(named name: String) -> UIColor { return .black } } return DefaultTheme() }() public typealias Value = ThemeProviding } /// The key for Vector Drawable resources. public struct ResourceKey: EnvironmentKey { public static let defaultValue: ResourceProviding = { struct DefaultResources: ResourceProviding { func colorFromResources(named name: String) -> UIColor { return .black } } return DefaultResources() }() public typealias Value = ResourceProviding } @available(iOS 13.0, OSX 10.15, tvOS 13.0, *) public extension EnvironmentValues { /// The theme to use for `VectorDrawables`. var vectorDrawableTheme: ThemeProviding { get { return self[ThemeKey.self] } set { self[ThemeKey.self] = newValue } } /// The Resources to use for `VectorDrawables`. /// /// Use `ResourceKey.defaultValue` to set the value for this /// before using it in `environment()`, as this will probably be accessed /// before `makeUIView` is called. var vectorDrawableResources: ResourceProviding { get { return self[ResourceKey.self] } set { self[ResourceKey.self] = newValue } } } #endif