diff --git a/Example/EpoxyExample/ViewControllers/SwiftUI/EpoxyInSwiftUISizingStrategiesViewController.swift b/Example/EpoxyExample/ViewControllers/SwiftUI/EpoxyInSwiftUISizingStrategiesViewController.swift index 3bf3727..26e2b3f 100644 --- a/Example/EpoxyExample/ViewControllers/SwiftUI/EpoxyInSwiftUISizingStrategiesViewController.swift +++ b/Example/EpoxyExample/ViewControllers/SwiftUI/EpoxyInSwiftUISizingStrategiesViewController.swift @@ -79,17 +79,17 @@ extension SwiftUIMeasurementContainerStrategy: Identifiable, CaseIterable { var displayString: String { switch self { case .automatic: - "Automatic" + return "Automatic" case .proposed: - "Proposed" + return "Proposed" case .intrinsicHeightProposedOrIntrinsicWidth: - "Intrinsic Height, Proposed Width or Intrinsic Width" + return "Intrinsic Height, Proposed Width or Intrinsic Width" case .intrinsicHeightProposedWidth: - "Intrinsic Height, Proposed Width" + return "Intrinsic Height, Proposed Width" case .intrinsicWidthProposedHeight: - "Intrinsic Width, Proposed Height" + return "Intrinsic Width, Proposed Height" case .intrinsic: - "Intrinsic" + return "Intrinsic" } } diff --git a/Sources/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift b/Sources/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift index 04c54a1..25b16fc 100644 --- a/Sources/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift +++ b/Sources/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift @@ -65,7 +65,7 @@ extension MeasuringViewRepresentable { size = uiView.measuredFittingSize } - #if swift(>=5.7) // Proxy check for being built with the iOS 15 SDK + #if swift(>=5.7.1) // Proxy check for being built with the iOS 15 SDK @available(iOS 16.0, tvOS 16.0, macOS 13.0, *) public func sizeThatFits( _ proposal: ProposedViewSize, @@ -90,7 +90,13 @@ extension MeasuringViewRepresentable { { nsView.strategy = sizing let children = Mirror(reflecting: proposedSize).children - nsView.proposedSize = proposal.viewTypeValue + nsView.proposedSize = .init( + width: ( + children.first { $0.label == "width" }? + .value as? CGFloat ?? ViewType.noIntrinsicMetric).constraintSafeValue, + height: ( + children.first { $0.label == "height" }? + .value as? CGFloat ?? ViewType.noIntrinsicMetric).constraintSafeValue) size = nsView.measuredFittingSize } @@ -111,7 +117,7 @@ extension MeasuringViewRepresentable { } #endif -#if swift(>=5.7) // Proxy check for being built with the iOS 15 SDK +#if swift(>=5.7.1) // Proxy check for being built with the iOS 15 SDK @available(iOS 16.0, tvOS 16.0, macOS 13.0, *) extension ProposedViewSize { /// Creates a size by replacing `nil`s with `UIView.noIntrinsicMetric` diff --git a/Sources/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift b/Sources/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift index 2658a5b..8374d6b 100644 --- a/Sources/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift +++ b/Sources/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift @@ -82,7 +82,7 @@ public final class SwiftUIMeasurementContainer: ViewType { // The proposed size is only used by the measurement, so just re-measure. _measuredFittingSize = nil - setNeedsUpdateConstraints() + setNeedsUpdateConstraintsForPlatform() } } @@ -165,7 +165,7 @@ public final class SwiftUIMeasurementContainer: ViewType { /// The cached `measuredFittingSize` to prevent unnecessary re-measurements. private var _measuredFittingSize: CGSize? { didSet { - setNeedsUpdateConstraints() + setNeedsUpdateConstraintsForPlatform() } } @@ -278,9 +278,25 @@ public final class SwiftUIMeasurementContainer: ViewType { } } + private func setNeedsUpdateConstraintsForPlatform() { + #if os(iOS) || os(tvOS) + setNeedsUpdateConstraints() + #elseif os(macOS) + needsUpdateConstraints = true + #endif + } + + private func updateConstraintsForPlatformIfNeeded() { + #if os(iOS) || os(tvOS) + updateConstraintsIfNeeded() + #elseif os(macOS) + updateConstraintsForSubtreeIfNeeded() + #endif + } + /// Measures the `uiView`, storing the resulting size in `measuredIntrinsicContentSize`. private func measureView() -> CGSize { - updateConstraintsIfNeeded() + updateConstraintsForPlatformIfNeeded() latestMeasurementBoundsSize = bounds.size var measuredSize: CGSize @@ -299,7 +315,7 @@ public final class SwiftUIMeasurementContainer: ViewType { measuredSize.height = ViewType.noIntrinsicMetric case .intrinsicHeightProposedOrIntrinsicWidth: - let fittingSize = content.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) + let fittingSize = content.systemLayoutFittingIntrinsicSize() measuredSize = CGSize( width: min(fittingSize.width, proposedSize.width > 0 ? proposedSize.width : fittingSize.width), height: fittingSize.height)