Repository navigation
Pass the clip rect through iOS views that don't clip subviews - #59246
Closed
hryhoriiK97 wants to merge 1 commit into
Closed
hryhoriiK97 wants to merge 1 commit into
hryhoriiK97 wants to merge 1 commit into
Conversation
When a ScrollView updates clipped subviews, every view on the way down converts the clip rect into its own coordinates and passes it on, although only views with removeClippedSubviews use it, and those convert it from the view it is relative to themselves. Views that don't clip now pass the rect on unchanged, still relative to the same view, so a clipping view converts it once instead of once per level. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Closing in favor of #59284, which skips this walk entirely when no view has |
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.
Summary:
RCTScrollViewComponentViewupdates clipped subviews by callingupdateClippedSubviewsWithClipRect:relativeToView:on its scroll view, after every mounting transaction and while scrolling. The call walks every view in the scroll view's content: views withremoveClippedSubviews(RCTViewComponentView) unmount the children outside the rect, and every other view forwards the call to its subviews through the default implementation inUIView+ComponentViewProtocol.mm.Current behavior. The default implementation converts the rect into its own coordinates (
convertRect:toView:) and passes it on relative to itself, so every view on the way does one conversion, although none of them uses the rect. The only views that use it, those withremoveClippedSubviews, convert it from the view it is relative to themselves. In a FlatList withoutremoveClippedSubviews(the default on iOS), every walk converts the rect once per view in the visible content and uses none of the results.With this change. A view that doesn't clip passes the rect on unchanged, still relative to the same view. A view with
removeClippedSubviewsconverts it from that view as before, in one conversion instead of one per level. For translations and scales the result is the same; with two or more rotated or skewed views between the scroll view and a clipping view, one conversion gives the exact bounding box where converting level by level grows it at each level, so such a view clips slightly more precisely.Changelog:
[IOS] [CHANGED] - Updating clipped subviews of a ScrollView no longer converts the clip rect in every view it passes through
Test Plan:
clang-format --dry-run --Werroron the changed file passes.xcodebuildin Release and run on a physical iPhone 15 Pro (iOS 26.6.1).removeClippedSubviewsreceives both ways (converted at every level, and passed through unchanged and converted once), 6,394 rects over 3,205 walks while flinging 1000 cards inside aremoveClippedSubviewsview, behind an offset wrapper, were equal within 0.01 pt. With the wrapper rotated by 2°, 6,358 rects over 3,187 walks were equal as well.expo-modules-core's SwiftUI virtual views,react-native-nano-icons) ignore the rect. An override that converts the rect fromclipView, asRCTViewComponentViewdoes, is unaffected; one that assumedclipViewis its direct superview would now get an ancestor._remountChildren. iPhone 15 Pro, Release:removeClippedSubviews, 20 flings down and 20 up per launch (18,000 walks, 123 views each)removeClippedSubviewsview, 16 flings down and 16 up per launch (4,000 walks, 30 views each)When the content clips, the walk stops at the clipping view and its time goes into comparing and remounting that view's children, so there is little to save.
🤖 Generated with Claude Code