Repository navigation
Conversation
On iOS 26 and later, a right swipe that started anywhere on a pushed screen popped it, even from the middle or the right-hand side. That broke swipe-to-reply and any gesture-area @swipe on pushed screens. Our navigation code has no custom pan. iOS 26 added a second pop gesture to UINavigationController, interactiveContentPopGestureRecognizer, and SwiftUI's NavigationStack turns it on. The left-edge swipe is still the separate interactivePopGestureRecognizer. SwiftUI has no modifier to turn the content gesture off, so both NavigationStacks (stack chrome and the per-tab stack) now carry a zero-size UIKit view that finds its UINavigationController once it is in a window and disables that one recognizer. It sits on every level, root and pushed, so a stack that opens straight onto a pushed screen is covered too. The edge swipe and the back button are untouched. The call is behind #available(iOS 26.0, *) for older devices and #if compiler(>=6.2) so it compiles out on pre-Xcode-26 toolchains. Fixes #470 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
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 #470
On iOS 26 and later, a right swipe that starts anywhere on a pushed screen pops it. That includes the middle of the screen and the right-hand fifth. It takes those swipes away from the app, so swipe-to-reply or a gesture area's
@swipeon a pushed screen never fires.This isn't our code. There is no custom pan in the navigation renderers. iOS 26 added a second pop gesture to
UINavigationController,interactiveContentPopGestureRecognizer, and SwiftUI'sNavigationStackturns it on. The left-edge swipe is still the olderinteractivePopGestureRecognizer. I confirmed this with logging on a debug build. A drag that UIKit didn't treat as an edge touch was handled by the recognizer namedUINavigationController.contentSwipe. An edge drag was handled byUINavigationController.edgeSwipe.The change
SwiftUI has no modifier to turn the content gesture off. So I added
EdgeOnlySwipeBack, a zero-size UIKit view placed inside eachNavigationStack. Once it is in a window it walks up the responder chain to its navigation controller and disablesinteractiveContentPopGestureRecognizer. Nothing else is touched, so the edge swipe and the back chevron work as before.It goes on both stacks that can push: the stack chrome renderer and the per-tab stack in the tabs renderer. It is attached at every level, root and pushed, because a stack can open straight onto a pushed screen with its root never on screen. Plain screens without native chrome don't use a navigation stack at all, so they had no swipe-back before this and still don't.
The call sits behind
#available(iOS 26.0, *)for older devices. It is also inside#if compiler(>=6.2), the gate #364 proposes for the other iOS 26 calls, so it compiles out on pre-Xcode-26 toolchains instead of adding another build error there.What to look at
UINavigationController. Inside tabs that is the tab's own stack, which is what we want.Open question
Should edge-only be configurable? Some apps may want the iOS 26 full-width swipe back. I didn't build an option. This PR makes edge-only the behaviour everywhere, which matches iOS before 26 and Android.
Testing
Test app built from mobile-starter on the iPhone 18 Pro simulator (iOS 27), with a stack layout and a tabs layout. Each pushed screen had a plain area, a gesture area with
@swipe, and a gesture area with:pan-x. I ran the same checks on main and on this branch, on a stack push and on a push inside a tab. Results were the same for both.@swipearea: popped on main before the swipe could fire. Now it firesright.:pan-xarea: the card followed the finger on both main and this branch. Its drag grabs the touch first, so the content gesture never won there.No PHP changed.
🤖 Generated with Claude Code