feat: Add iOS 27 support - #7239
Open
cadivus wants to merge 12 commits into
Open
Conversation
Replace raw NSError in FlutterError.details with nil in didFailToRegisterForRemoteNotificationsWithError. NSError is not supported by FlutterStandardCodec and causes NSInternalInconsistencyException on encode.
Add FlutterSceneLifeCycleDelegate conformance and register via addSceneDelegate. Implement scene:willConnectTo:options: for launch notification extraction from connectionOptions.notificationResponse, sceneDidBecomeActive for token registration, and sceneDidEnterBackground for launch notification cleanup. Existing AppDelegate methods retained for backward compatibility.
The scene callbacks added for UIScene support run once per connected scene, while the state they drive is per application. Guard them accordingly: - scene:willConnectToSession:options: returned true, which tells FlutterPluginSceneLifeCycleDelegate the connection was handled. The forwarding stops at the first plugin that returns true and nils out the connectionOptions, so returning true here hid the event, and the launch notification, from every plugin registered after this one. The plugin only reads the options, so it now returns false. - sceneDidBecomeActive registered for remote notifications on every scene activation. In a multi scene App that repeats the APNs round trip per scene and emits a duplicate token, or duplicate DeviceTokenError, on the Dart event stream. It now registers only when no other scene is already active. - sceneDidEnterBackground cleared the shared launchNotification whenever any scene was backgrounded, which could discard a tap another, still foregrounded, scene had not handed to Flutter yet. It now waits for the last foreground scene to leave. Hosts that have not adopted UIScene are unaffected: the AppDelegate methods in +AppDelegate.swift are unchanged and remain the active path there.
…ugin The previous tests lived in the amplify_push_notifications example and asserted on values they rebuilt inline, so they passed with the fixes reverted: the details map test rebuilt the dictionary literal instead of reading it back from the plugin, and the activation state test reduced to XCTAssertNotEqual(.unattached, .background), a statement about the UIKit enum. Replace them with tests in the existing unit_tests target, which can @testable import the plugin and already has the registrar, flutter api and UIApplication swizzling mocks: - didFailToRegisterForRemoteNotifications forwards a {domain, code} map, and no NSError, so FlutterStandardCodec can encode it - register(with:) installs both the application and the scene delegate - scene:willConnectToSession:options: returns false, leaving the event for the plugins after this one, and keeps a launch notification recorded via the AppDelegate path when the options were already consumed - sceneDidBecomeActive registers for remote notifications - sceneDidEnterBackground nullifies the launch notification MockFlutterPluginRegistrar gains the addSceneDelegate implementation that FlutterPluginRegistrar now requires.
connectedScenes is an unordered Set, so connectedScenes.first can return a background scene, or a scene without a screen, and the ?? fallbacks then reported a 0x0 screen: amplify_auth_cognito sent that to Cognito as ASF context data, and DeviceInfo.screenBounds returned .zero. Look for a foregroundActive scene first, then foregroundInactive, and only then fall back to any window scene. Cognito now leaves screenWidthPixels and screenHeightPixels unset when no scene has a screen, rather than sending 0, as both fields are optional in the pigeon message. UIScreen.main is deprecated as of iOS 26. connectedScenes is available from iOS 13, which both packages already require.
The unit_tests target did not compile against Flutter 3.44, so none of these tests had been running: - FlutterPluginRegistrar gained the viewController property and valuePublished(byPlugin:), which MockFlutterPluginRegistrar was missing, so the mock no longer conformed - setBadgeCountWithBadgeCount takes an NSInteger, so the `as NSNumber` cast on the argument no longer type checked - the pigeon generated types live in the amplify_push_notifications_objc module, which @testable import amplify_push_notifications does not re-export, leaving PushNotificationsFlutterApi unresolved With these fixed the whole target builds and all 21 tests pass, including the scene life cycle coverage added in the previous commit.
The iOS 27 SDK only supports deployment targets from 15.0, so building any example on it fails outright rather than warning: Target Integrity (Xcode): The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 13.0, but the range of supported deployment target versions is 15.0 to 27.0.x. Could not build the application for the simulator. Xcode 26.4 still accepts 12.0 and above, which is why this only shows up on the iOS 27 CI runners. Raise every example to 15.0: the platform line in 12 Podfiles, the IPHONEOS_DEPLOYMENT_TARGET in the Runner projects, and the amplify_api post_install hook that pinned the Pods project to 13.0. Also drop the MinimumOSVersion key from AppFrameworkInfo.plist, which the current Flutter template no longer generates and which still claimed 11.0 or 12.0. This only covers the examples. The published packages still declare iOS 13.0 in their podspecs and Package.swift files, as raising that is a breaking change for consumers and belongs in its own change.
Raising the Podfile platform was not enough. podhelper.rb generates a stand-in Flutter podspec with a hardcoded 13.0 deployment target, and its own flutter_additional_ios_build_settings only clears IPHONEOS_DEPLOYMENT_TARGET for pods below 13.0, so the Flutter pod kept 13.0 in Pods.xcodeproj and the build still failed on the iOS 27 SDK: Target Integrity (Xcode): The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 13.0, but the range of supported deployment target versions is 15.0 to 27.0.x. .../example/ios/Pods/Pods.xcodeproj Override the setting for every Pods target in post_install, matching what the amplify_api example already did for a different reason. Also raise the iOS platform in the plugin podspecs and Package.swift files, which is what pod install and Swift Package Manager resolve against. The macOS deployment targets are untouched.
Flutter 3.41 makes UIScene the default, and without it the tooling cannot attach to the app on the iOS 27 simulator, so the integration tests never start: Error waiting for a debug connection: The log reader failed unexpectedly Failed to load ...main_test.dart: Unable to start the app on the device. Ran the migration the Flutter CLI performs for app developers, by building each example once and letting it report "Finished migration to UIScene lifecycle". It adds the UIApplicationSceneManifest to Info.plist and moves plugin registration from didFinishLaunchingWithOptions to didInitializeImplicitFlutterEngine. The CLI skips the migration when it does not recognise the AppDelegate, and it compares against its templates verbatim, so our copyright header alone was enough to opt every example out of it. The header was removed for the migration and restored afterwards. No SceneDelegate subclass is added: none of these examples use the deprecated UI life cycle events, so they use Flutter's own FlutterSceneDelegate, which is what the CLI configures.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7239 +/- ##
=======================================
Coverage 40.97% 40.97%
=======================================
Files 121 121
Lines 8273 8273
Branches 3598 3598
=======================================
Hits 3390 3390
Misses 4883 4883 🚀 New features to boost your workflow:
|
cadivus
marked this pull request as ready for review
August 6, 2026 12:22
cadivus
enabled auto-merge (squash)
August 6, 2026 12:23
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.
Same as #7234 but without upgrading the workflows to a beta Xcode version.