diff --git a/CHANGELOG.md b/CHANGELOG.md index dca721f..0f3333a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://github.com/airbnb/epoxy-ios/compare/0.10.0...HEAD) +### Added +- Expose `forceLayout` in `EpoxySwiftUIHostingView` for updating the hosting view size from outside. + ### Changed - `AnyItemModel` now implements the `ErasedContentProviding` protocol. - Updated `ErasedContentProviding` protocol to use its type name instead of `Self` in the keys of its `EpoxyModelProperty` properties `contentProperty` and `isContentEqualProperty `. diff --git a/Sources/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift b/Sources/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift index d69a2a8..c9a7924 100644 --- a/Sources/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift +++ b/Sources/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift @@ -198,12 +198,9 @@ public final class EpoxySwiftUIHostingView: UIView, EpoxyableVie // The view controller must be added to the view controller hierarchy to measure its content. addViewControllerIfNeededAndReady() - // 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() + // In this method `setNeedsLayout` and `layoutIfNeeded` are called. We need to layout the view to ensure it gets resized properly when cells are re-used + // In this method `invalidateIntrinsicContentSize` is called. This is required to ensure that views with new content are properly resized. + forceLayout() } public override func layoutMarginsDidChange() { @@ -234,9 +231,7 @@ public final class EpoxySwiftUIHostingView: UIView, EpoxyableVie // to be more common with top and bottom bars, since they can be laid out early during view // controller transitions. If this works well, we may make this the default behavior for all // SwiftUI views. - viewController.view.setNeedsLayout() - viewController.view.layoutIfNeeded() - viewController.view.invalidateIntrinsicContentSize() + forceLayout() } else { // Allow the layout margins update to fully propagate through to the SwiftUI View before // invalidating the layout. @@ -246,6 +241,14 @@ public final class EpoxySwiftUIHostingView: UIView, EpoxyableVie } } + /// Force relayout the UIHostingView and invalidate its intrinsic content size. + /// This is used for updating the view size manually. + public func forceLayout() { + viewController.view.setNeedsLayout() + viewController.view.layoutIfNeeded() + viewController.view.invalidateIntrinsicContentSize() + } + public func handleWillDisplay(animated: Bool) { guard state != .appeared, window != nil else { return } transition(to: .appearing(animated: animated))