Fix #5163: status-bar tap scrolls to top only once per Form#5164
Merged
Conversation
The iOS "tap status bar to scroll to top" proxy (CN1StatusBarTapProxyView) is only eligible for UIStatusBarTapAction routing while its contentOffset.y is > 0. cn1FireStatusBarTap reset that offset back to (0,1) synchronously, but it runs from inside scrollViewShouldScrollToTop: while UIKit is still processing the tap, so the reset was clobbered and the proxy settled at offset 0. iOS then stopped delivering further taps until the next viewDidAppear re-pinned the offset -- producing the reported "scroll to top only works once after showing a Form" behavior. Bounce the re-arm to the next main-queue turn so UIKit finishes the gesture first and the (0,1) offset actually sticks, keeping the proxy eligible for every subsequent tap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
Collaborator
Author
|
Compared 122 screenshots: 122 matched. Benchmark Results
Detailed Performance Metrics
|
Collaborator
Author
|
Compared 103 screenshots: 103 matched. Benchmark Results
Build and Run Timing
|
Collaborator
Author
|
Compared 122 screenshots: 122 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
Refresh the 34 Mac native (Catalyst/Metal) goldens that the build-mac-native job reported as "different", adopting the images generated by the scripts-mac-native run on this branch. These are all theme/rendering drift (ButtonTheme, DialogTheme, ToolbarTheme, etc.) on the maturing Mac slice; the 88 other tests still match and no test is newly missing. Generated by: scripts-mac-native run 26923979109. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Problem
Reported in #5163: on device (iPhone 15 Pro Max, iOS 26.5), tapping the status bar scrolls the Form to the top, but only once after the Form is shown. Scroll down again and the next tap does nothing; switching to another Form and back re-enables exactly one more working tap. The simulator's "iOS Status Bar Tap" menu can't reproduce it because that path bypasses the proxy.
Root cause
The "tap status bar → scroll to top" feature uses a synthetic
UIScrollViewproxy (CN1StatusBarTapProxyView) pinned to the status-bar strip at theUIWindowlevel. iOS only routesUIStatusBarTapActionto a scroll view whosecontentOffset.y > 0(i.e. it looks "scrolled away from top"), so the proxy is kept atcontentOffset = (0,1)to stay eligible.cn1FireStatusBarTap()re-armed that offset synchronously — but it runs from insidescrollViewShouldScrollToTop:while UIKit is still mid-tap. UIKit settles the proxy back toward the top after the delegate returns, clobbering our reset, so the proxy ends up at offset 0 and is no longer eligible. iOS then stops delivering taps until the nextviewDidAppearre-pins the offset — hence "works exactly once per Form appearance."The Java half (
Form.findScrollableChild+scrollRectToVisible) is stateless and would scroll on every invocation, which is what localizes the bug to the native re-arm.Fix
Bounce the
(0,1)re-arm to the next main-queue turn viadispatch_async, so UIKit finishes processing the gesture before we restore the offset. The re-arm then sticks and the proxy stays eligible for every subsequent tap. Low-risk: it only changes when the existing one-line reset runs, anddispatch_asyncto the main queue is safe regardless of which threadcn1FireStatusBarTapis invoked from (including the instrumented test path).Verification
This is device-only (the simulator status-bar menu bypasses the proxy). The exposed diagnostic counter can confirm before/after:
Before the fix the count stops incrementing on the second tap; after the fix it increments on every tap.
🤖 Generated with Claude Code