From 286e592194da983137fc023d4bfafae3839b2bc2 Mon Sep 17 00:00:00 2001 From: flutteractionsbot <154381524+flutteractionsbot@users.noreply.github.com> Date: Mon, 15 Sep 2025 10:40:04 -0700 Subject: [PATCH] [CP-beta][ios]Do not re-add delaying recognizer on iOS 26 (#175299) This pull request is created by [automatic cherry pick workflow](https://github.com/flutter/flutter/blob/main/docs/releases/Flutter-Cherrypick-Process.md#automatically-creates-a-cherry-pick-request) Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request. ### Issue Link: What is the link to the issue this cherry-pick is addressing? https://github.com/flutter/flutter/issues/174513 ### Changelog Description: Explain this cherry pick in one line that is accessible to most Flutter developers. See [best practices](https://github.com/flutter/flutter/blob/main/docs/releases/Hotfix-Documentation-Best-Practices.md) for examples Fix a bug where platform view's gesture blocking fails to work on iOS 26 ### Impact Description: What is the impact (ex. visual jank on Samsung phones, app crash, cannot ship an iOS app)? Does it impact development (ex. flutter doctor crashes when Android Studio is installed), or the shipping production app (the app crashes on launch) All platform views (e.g. web view, map, etc) on iOS 26 ### Workaround: Is there a workaround for this issue? No ### Risk: What is the risk level of this cherry-pick? ### Test Coverage: Are you confident that your fix is well-tested by automated tests? ### Validation Steps: What are the steps to validate that this fix works? As explained in the linked issue above, interact with the flutter UI on top of the platform view. Notice that the platform view still receives the touches, despite that the platform view is under flutter UI and it shouldn't receive the touches. This only happens on iOS 26. --- .../framework/Source/FlutterPlatformViews.mm | 6 +++++- .../Source/FlutterPlatformViewsTest.mm | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 225ab326bb6..d88b9bb548b 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -587,7 +587,11 @@ static BOOL _preparedOnce = NO; // from the web view plugin level. Right now we only observe this issue for // FlutterPlatformViewGestureRecognizersBlockingPolicyEager, but we should try it if a similar // issue arises for the other policy. - if (@available(iOS 18.2, *)) { + if (@available(iOS 26.0, *)) { + // This workaround does not work on iOS 26. + // TODO(hellohuanlin): find a solution for iOS 26, + // https://github.com/flutter/flutter/issues/175099. + } else if (@available(iOS 18.2, *)) { // This workaround is designed for WKWebView only. The 1P web view plugin provides a // WKWebView itself as the platform view. However, some 3P plugins provide wrappers of // WKWebView instead. So we perform DFS to search the view hierarchy (with a depth limit). diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index e65dc4af721..20b4e2936c8 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -3198,7 +3198,14 @@ fml::RefPtr GetDefaultTaskRunner() { [(FlutterTouchInterceptingView*)touchInteceptorView blockGesture]; - if (@available(iOS 18.2, *)) { + BOOL shouldReAddDelayingRecognizer = NO; + if (@available(iOS 26.0, *)) { + // TODO(hellohuanlin): find a solution for iOS 26, + // https://github.com/flutter/flutter/issues/175099. + } else if (@available(iOS 18.2, *)) { + shouldReAddDelayingRecognizer = YES; + } + if (shouldReAddDelayingRecognizer) { // Since we remove and add back delayingRecognizer, it would be reordered to the last. XCTAssertEqual(touchInteceptorView.gestureRecognizers[0], forwardingRecognizer); XCTAssertEqual(touchInteceptorView.gestureRecognizers[1], delayingRecognizer); @@ -3261,7 +3268,14 @@ fml::RefPtr GetDefaultTaskRunner() { [(FlutterTouchInterceptingView*)touchInteceptorView blockGesture]; - if (@available(iOS 18.2, *)) { + BOOL shouldReAddDelayingRecognizer = NO; + if (@available(iOS 26.0, *)) { + // TODO(hellohuanlin): find a solution for iOS 26, + // https://github.com/flutter/flutter/issues/175099. + } else if (@available(iOS 18.2, *)) { + shouldReAddDelayingRecognizer = YES; + } + if (shouldReAddDelayingRecognizer) { // Since we remove and add back delayingRecognizer, it would be reordered to the last. XCTAssertEqual(touchInteceptorView.gestureRecognizers[0], forwardingRecognizer); XCTAssertEqual(touchInteceptorView.gestureRecognizers[1], delayingRecognizer);