diff --git a/CHANGELOG.md b/CHANGELOG.md index a19fde13..3a459bca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `forcesEarlySwiftUIRendering` flag to `CollectionViewConfiguration` to test a SwiftUI layout approach to resolve an issue that could cause collection view cells to layout with unexpected dimensions +- Made new layout-based SwiftUI cell rendering option the default. ## [0.10.0](https://github.com/airbnb/epoxy-ios/compare/0.9.0...0.10.0) - 2023-06-29 diff --git a/Sources/EpoxyCollectionView/CollectionView/CollectionView.swift b/Sources/EpoxyCollectionView/CollectionView/CollectionView.swift index a9f728ab..0f9a67ff 100644 --- a/Sources/EpoxyCollectionView/CollectionView/CollectionView.swift +++ b/Sources/EpoxyCollectionView/CollectionView/CollectionView.swift @@ -445,7 +445,6 @@ open class CollectionView: UICollectionView { } cell.itemPath = itemPath - cell.forcesEarlySwiftUIRendering = configuration.forcesEarlySwiftUIRendering let metadata = ItemCellMetadata( traitCollection: traitCollection, @@ -470,7 +469,6 @@ open class CollectionView: UICollectionView { animated: Bool) { supplementaryView.itemPath = itemPath - supplementaryView.forcesEarlySwiftUIRendering = configuration.forcesEarlySwiftUIRendering model.configure( reusableView: supplementaryView, traitCollection: traitCollection, diff --git a/Sources/EpoxyCollectionView/CollectionView/CollectionViewConfiguration.swift b/Sources/EpoxyCollectionView/CollectionView/CollectionViewConfiguration.swift index 0eccd871..c721ea4e 100644 --- a/Sources/EpoxyCollectionView/CollectionView/CollectionViewConfiguration.swift +++ b/Sources/EpoxyCollectionView/CollectionView/CollectionViewConfiguration.swift @@ -13,13 +13,11 @@ public struct CollectionViewConfiguration { public init( usesBatchUpdatesForAllReloads: Bool = true, usesCellPrefetching: Bool = true, - usesAccurateScrollToItem: Bool = true, - forcesEarlySwiftUIRendering: Bool = true) + usesAccurateScrollToItem: Bool = true) { self.usesBatchUpdatesForAllReloads = usesBatchUpdatesForAllReloads self.usesCellPrefetching = usesCellPrefetching self.usesAccurateScrollToItem = usesAccurateScrollToItem - self.forcesEarlySwiftUIRendering = forcesEarlySwiftUIRendering } // MARK: Public @@ -68,10 +66,4 @@ public struct CollectionViewConfiguration { /// /// - SeeAlso: `CollectionViewScrollToItemHelper` public var usesAccurateScrollToItem: Bool - - /// Flag to use a semi-private API to force an early render of a SwiftUI view embedded in a `UIHostingController`. This is used - /// to synchronously resize after updating the `rootView`. When disabled, layout is forced using standard UIKit functions, a newer - /// approach which is being tested for viability and to resolve issues where SwiftUI views in collection view cells undergo a layout pass - /// with unexpected dimensions. - public var forcesEarlySwiftUIRendering: Bool } diff --git a/Sources/EpoxyCollectionView/CollectionView/ReusableViews/CollectionViewCell.swift b/Sources/EpoxyCollectionView/CollectionView/ReusableViews/CollectionViewCell.swift index c34f60b4..df49ca90 100644 --- a/Sources/EpoxyCollectionView/CollectionView/ReusableViews/CollectionViewCell.swift +++ b/Sources/EpoxyCollectionView/CollectionView/ReusableViews/CollectionViewCell.swift @@ -7,7 +7,7 @@ import UIKit // MARK: - CollectionViewCell /// An internal cell class for use in a `CollectionView`. -public final class CollectionViewCell: UICollectionViewCell, ItemCellView, SwiftUIRenderingConfigurable { +public final class CollectionViewCell: UICollectionViewCell, ItemCellView { // MARK: Lifecycle @@ -27,13 +27,6 @@ public final class CollectionViewCell: UICollectionViewCell, ItemCellView, Swift public var selectedBackgroundColor: UIColor? - /// See `CollectionViewConfiguration.forcesEarlySwiftUIRendering` for an explanation of this behavior. - public var forcesEarlySwiftUIRendering = true { - didSet { - updateForcesEarlySwiftUIRendering() - } - } - override public var isSelected: Bool { didSet { updateVisualHighlightState(isSelected) @@ -66,8 +59,6 @@ public final class CollectionViewCell: UICollectionViewCell, ItemCellView, Swift view.topAnchor.constraint(equalTo: contentView.topAnchor), view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) - - updateForcesEarlySwiftUIRendering() } override public func preferredLayoutAttributesFitting( @@ -161,12 +152,6 @@ public final class CollectionViewCell: UICollectionViewCell, ItemCellView, Swift } } - private func updateForcesEarlySwiftUIRendering() { - if let configurableView = view as? SwiftUIRenderingConfigurable { - configurableView.forcesEarlySwiftUIRendering = forcesEarlySwiftUIRendering - } - } - } // MARK: EphemeralCachedStateView diff --git a/Sources/EpoxyCollectionView/CollectionView/ReusableViews/CollectionViewReusableView.swift b/Sources/EpoxyCollectionView/CollectionView/ReusableViews/CollectionViewReusableView.swift index 3ac74685..d65906cb 100644 --- a/Sources/EpoxyCollectionView/CollectionView/ReusableViews/CollectionViewReusableView.swift +++ b/Sources/EpoxyCollectionView/CollectionView/ReusableViews/CollectionViewReusableView.swift @@ -5,7 +5,7 @@ import EpoxyCore import UIKit /// An internal collection reusable view class for use in a `CollectionView`. -public final class CollectionViewReusableView: UICollectionReusableView, SwiftUIRenderingConfigurable { +public final class CollectionViewReusableView: UICollectionReusableView { // MARK: Lifecycle @@ -23,13 +23,6 @@ public final class CollectionViewReusableView: UICollectionReusableView, SwiftUI public private(set) var view: UIView? - /// See `CollectionViewConfiguration.forcesEarlySwiftUIRendering` for an explanation of this behavior. - public var forcesEarlySwiftUIRendering = false { - didSet { - updateForcesEarlySwiftUIRendering() - } - } - /// Pass a view for this view's element kind and reuseID that the view will pin to its edges. public func setViewIfNeeded(view: UIView) { if self.view != nil { @@ -47,8 +40,6 @@ public final class CollectionViewReusableView: UICollectionReusableView, SwiftUI view.bottomAnchor.constraint(equalTo: bottomAnchor), ]) self.view = view - - updateForcesEarlySwiftUIRendering() } override public func preferredLayoutAttributesFitting( @@ -86,12 +77,4 @@ public final class CollectionViewReusableView: UICollectionReusableView, SwiftUI /// post-update data. var itemPath: SupplementaryItemPath? - // MARK: Private - - private func updateForcesEarlySwiftUIRendering() { - if let configurableView = view as? SwiftUIRenderingConfigurable { - configurableView.forcesEarlySwiftUIRendering = forcesEarlySwiftUIRendering - } - } - } diff --git a/Sources/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift b/Sources/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift index e93ca373..d7ab1933 100644 --- a/Sources/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift +++ b/Sources/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift @@ -57,7 +57,7 @@ extension CallbackContextEpoxyModeled /// the API is private and 3) the `_UIHostingView` doesn't not accept setting a new `View` instance. /// /// - SeeAlso: `EpoxySwiftUIHostingController` -public final class EpoxySwiftUIHostingView: UIView, EpoxyableView, SwiftUIRenderingConfigurable { +public final class EpoxySwiftUIHostingView: UIView, EpoxyableView { // MARK: Lifecycle @@ -130,9 +130,6 @@ public final class EpoxySwiftUIHostingView: UIView, EpoxyableVie } } - /// See `CollectionViewConfiguration.forcesEarlySwiftUIRendering` for an explanation of this behavior. - public var forcesEarlySwiftUIRendering = true - public override func didMoveToWindow() { super.didMoveToWindow() @@ -186,18 +183,9 @@ public final class EpoxySwiftUIHostingView: UIView, EpoxyableVie // The view controller must be added to the view controller hierarchy to measure its content. addViewControllerIfNeededAndReady() - if forcesEarlySwiftUIRendering { - // As of iOS 15.2, `UIHostingController` now renders updated content asynchronously, and as such - // this view will get sized incorrectly with the previous content when reused unless we invoke - // this semi-private API. We couldn't find any other method to get the view to resize - // synchronously after updating `rootView`, but hopefully this will become a public API soon so - // we can remove this call. - viewController._render(seconds: 0) - } else { - // We need to layout the view to ensure it gets resized properly when cells are re-used - viewController.view.setNeedsLayout() - viewController.view.layoutIfNeeded() - } + // We need to layout the view to ensure it gets resized properly when cells are re-used + viewController.view.setNeedsLayout() + viewController.view.layoutIfNeeded() // This is required to ensure that views with new content are properly resized. viewController.view.invalidateIntrinsicContentSize() @@ -437,10 +425,3 @@ struct EpoxyHostingWrapper: View { } #endif - -// MARK: - SwiftUIRenderingConfigurable - -public protocol SwiftUIRenderingConfigurable: AnyObject { - /// See `CollectionViewConfiguration.forcesEarlySwiftUIRendering` for an explanation of this behavior. - var forcesEarlySwiftUIRendering: Bool { get set } -}