Skip to content

Commit

Permalink
Expose forceLayout in EpoxySwiftUIHostingView (#172)
Browse files Browse the repository at this point in the history
* Expose `forceLayout` in EpoxySwiftUIHostingView

* Add comments

---------

Co-authored-by: Shengqi Zhu <[email protected]>
  • Loading branch information
zetasq and Shengqi Zhu authored Aug 21, 2024
1 parent be1f8f0 commit 93178a5
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `.
Expand Down
21 changes: 12 additions & 9 deletions Sources/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,9 @@ public final class EpoxySwiftUIHostingView<RootView: View>: 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() {
Expand Down Expand Up @@ -234,9 +231,7 @@ public final class EpoxySwiftUIHostingView<RootView: View>: 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.
Expand All @@ -246,6 +241,14 @@ public final class EpoxySwiftUIHostingView<RootView: View>: 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))
Expand Down

0 comments on commit 93178a5

Please sign in to comment.