Skip to content

Commit

Permalink
Add EpoxySwiftUIHostingView (#619)
Browse files Browse the repository at this point in the history
  • Loading branch information
mohamede1945 authored Jan 11, 2024
1 parent a9c9fa8 commit 0cd8eca
Show file tree
Hide file tree
Showing 5 changed files with 593 additions and 0 deletions.
17 changes: 17 additions & 0 deletions UI/UIx/SwiftUI/Epoxy/DataIDProviding.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// From: https://github.com/airbnb/epoxy-ios/blob/ecee1ace58d58e3cc918a2dea28095de713b1112

// Created by eric_horacek on 12/1/20.
// Copyright © 2020 Airbnb Inc. All rights reserved.

// MARK: - DefaultDataID

/// The default data ID when none is provided.
public enum DefaultDataID: Hashable, CustomDebugStringConvertible {
case noneProvided

// MARK: Public

public var debugDescription: String {
"DefaultDataID.noneProvided"
}
}
49 changes: 49 additions & 0 deletions UI/UIx/SwiftUI/Epoxy/EpoxyIntrinsicContentSizeInvalidator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// From: https://github.com/airbnb/epoxy-ios/blob/ecee1ace58d58e3cc918a2dea28095de713b1112

// Created by matthew_cheok on 11/19/21.
// Copyright © 2021 Airbnb Inc. All rights reserved.

import SwiftUI

// MARK: - EpoxyIntrinsicContentSizeInvalidator

/// Allows the SwiftUI view contained in an Epoxy model to request the invalidation of
/// the container's intrinsic content size.
///
/// ```
/// @Environment(\.epoxyIntrinsicContentSizeInvalidator) var invalidateIntrinsicContentSize
///
/// var body: some View {
/// ...
/// .onChange(of: size) {
/// invalidateIntrinsicContentSize()
/// }
/// }
/// ```
public struct EpoxyIntrinsicContentSizeInvalidator {
// MARK: Public

public func callAsFunction() {
invalidate()
}

// MARK: Internal

let invalidate: () -> Void
}

// MARK: - EnvironmentValues

extension EnvironmentValues {
/// A means of invalidating the intrinsic content size of the parent `EpoxySwiftUIHostingView`.
public var epoxyIntrinsicContentSizeInvalidator: EpoxyIntrinsicContentSizeInvalidator {
get { self[EpoxyIntrinsicContentSizeInvalidatorKey.self] }
set { self[EpoxyIntrinsicContentSizeInvalidatorKey.self] = newValue }
}
}

// MARK: - EpoxyIntrinsicContentSizeInvalidatorKey

private struct EpoxyIntrinsicContentSizeInvalidatorKey: EnvironmentKey {
static let defaultValue = EpoxyIntrinsicContentSizeInvalidator(invalidate: { })
}
55 changes: 55 additions & 0 deletions UI/UIx/SwiftUI/Epoxy/EpoxySwiftUIHostingController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// From: https://github.com/airbnb/epoxy-ios/blob/ecee1ace58d58e3cc918a2dea28095de713b1112

// Created by eric_horacek on 10/8/21.
// Copyright © 2021 Airbnb Inc. All rights reserved.

import SwiftUI

#if !os(macOS)

// MARK: - EpoxySwiftUIUIHostingController

/// A `UIHostingController` that hosts SwiftUI views within an Epoxy container, e.g. an Epoxy
/// `CollectionView`.
///
/// Exposed publicly to allow consumers to reason about these view controllers, e.g. to opt
/// collection view cells out of automated view controller impression tracking.
///
/// - SeeAlso: `EpoxySwiftUIHostingView`
open class EpoxySwiftUIHostingController<Content: View>: UIHostingController<Content> {
// MARK: Lifecycle

/// Creates a `UIHostingController` that optionally ignores the `safeAreaInsets` when laying out
/// its contained `RootView`.
public convenience init(rootView: Content, ignoreSafeArea: Bool) {
self.init(rootView: rootView)

clearBackground()

// We unfortunately need to call a private API to disable the safe area. We can also accomplish
// this by dynamically subclassing this view controller's view at runtime and overriding its
// `safeAreaInsets` property and returning `.zero`. An implementation of that logic is
// available in this file in the `2d28b3181cca50b89618b54836f7a9b6e36ea78e` commit if this API
// no longer functions in future SwiftUI versions.
_disableSafeArea = ignoreSafeArea
}

// MARK: Open

override open func viewDidLoad() {
super.viewDidLoad()

clearBackground()
}

// MARK: Internal

func clearBackground() {
// A `UIHostingController` has a system background color by default as it's typically used in
// full-screen use cases. Since we're using this view controller to place SwiftUI views within
// other view controllers we default the background color to clear so we can see the views
// below, e.g. to draw highlight states in a `CollectionView`.
view.backgroundColor = .clear
}
}
#endif
Loading

0 comments on commit 0cd8eca

Please sign in to comment.