Use ImageRenderer for ideal size layout on iOS 16+#1071
Open
abrahamduran wants to merge 3 commits intopointfreeco:mainfrom
Open
Use ImageRenderer for ideal size layout on iOS 16+#1071abrahamduran wants to merge 3 commits intopointfreeco:mainfrom
abrahamduran wants to merge 3 commits intopointfreeco:mainfrom
Conversation
- Use ImageRenderer (iOS 16+) with ProposedViewSize(nil, nil) to get ideal size - Fall back to screen-width proposal for iOS 13-15 - Add tests for padding and Spacer views that expose the bug
db67873 to
0a51132
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1070
Summary
.sizeThatFitsis broken on modern iOS simulators.UIHostingController.sizeThatFits(in: .zero)returns the view's minimum compressed size instead of its ideal size, causing truncated text and collapsed layouts.The root cause:
CGSizecannot express "unspecified" dimensions. SwiftUI'sProposedViewSizesupportsnil(meaning "use your ideal size"), but there's noCGSizeequivalent — so there's no value you can pass toUIHostingController.sizeThatFits(in:)that means "ideal size."Changes
SwiftUIView.swift— For.sizeThatFitson iOS 16+, useImageRendererwithProposedViewSize(width: nil, height: nil)instead of theUIHostingController→UIWindow→layer.renderpipeline. This is the SwiftUI-native way to ask for ideal size.ImageRendererbypasses UIKit's trait system, soUITraitCollection.userInterfaceStyleis converted to SwiftUI's.colorSchemeenvironmentMainActor.assumeIsolatedis used becauseImageRendereris@MainActor-isolated but theasyncPullbackclosure is nonisolated (snapshot tests always run on main thread).deviceand.fixedlayouts are unchanged — they still use theUIHostingController/UIWindowpathiOS 13-15 fallback — Uses screen width with unconstrained height as a reasonable heuristic, since
ImageRendererisn't available.Tests — Two new tests that expose the bug:
testSwiftUIView_sizeThatFits_padding—Textwith.padding()(padding collapses with the old path)testSwiftUIView_sizeThatFits_spacer—HStackwithSpacer()(spacer gets crushed to zero with the old path)Note on baselines
The
testSwiftUIView_iOS.size-that-fits.pngbaseline was re-recorded with the newImageRendererpath. The new test baselines were recorded on an iPhone 17 simulator (@3x) — they may need re-recording on your CI's pinned simulator.