From a6754b45158ff0517b6d0f56a52e000e18be7c4c Mon Sep 17 00:00:00 2001 From: Aleksandr Lozhkovoi Date: Sat, 20 Jun 2026 01:30:12 +0200 Subject: [PATCH] Migrate ios_books SceneDelegate for UIScene (#2845) Part of flutter/flutter#176957 Migrated SceneDelegate.swift to use UI scene using this guideline https://docs.flutter.dev/release/breaking-changes/uiscenedelegate#migration-guide-for-flutter-apps for ios_books app image While testing this sample locally, I noticed a separate existing issue in `IosBooks/ViewController.swift`: the Google Books response is force-unwrapped. The unauthenticated request currently returns HTTP 429/quota errors in some environments, so `json["items"] as! [[String: Any]]` can crash at runtime. I kept this PR scoped to the UIScene migration only, but I can file or send a separate follow-up to make the sample parse the API response defensively, WDYT? ## Pre-launch Checklist - [x] I read the [Flutter Style Guide] _recently_, and have followed its advice. - [x] I signed the [CLA]. - [x] I read the [Contributors Guide]. - [x] I have added sample code updates to the [changelog]. - [x] I updated/added relevant documentation (doc comments with `///`). If you need help, consider asking for advice on the #hackers-devrel channel on [Discord]. [Flutter Style Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md [CLA]: https://cla.developers.google.com/ [Discord]: https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md [Contributors Guide]: https://github.com/flutter/samples/blob/main/CONTRIBUTING.md [changelog]: ../CHANGELOG.md Co-authored-by: Eric Windmill --- .../ios_books/IosBooks/SceneDelegate.swift | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/add_to_app/books/ios_books/IosBooks/SceneDelegate.swift b/add_to_app/books/ios_books/IosBooks/SceneDelegate.swift index a5cb47c5f..1c8670663 100644 --- a/add_to_app/books/ios_books/IosBooks/SceneDelegate.swift +++ b/add_to_app/books/ios_books/IosBooks/SceneDelegate.swift @@ -2,31 +2,68 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import Flutter import UIKit -class SceneDelegate: UIResponder, UIWindowSceneDelegate { +class SceneDelegate: UIResponder, UIWindowSceneDelegate, FlutterSceneLifeCycleProvider +{ + var sceneLifeCycleDelegate: FlutterPluginSceneLifeCycleDelegate = + FlutterPluginSceneLifeCycleDelegate() var window: UIWindow? func scene( - _ scene: UIScene, willConnectTo session: UISceneSession, + _ scene: UIScene, + willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions ) { - guard let _ = (scene as? UIWindowScene) else { return } + sceneLifeCycleDelegate.scene( + scene, + willConnectTo: session, + options: connectionOptions + ) } func sceneDidDisconnect(_ scene: UIScene) { + sceneLifeCycleDelegate.sceneDidDisconnect(scene) + } + + func sceneWillEnterForeground(_ scene: UIScene) { + sceneLifeCycleDelegate.sceneWillEnterForeground(scene) } func sceneDidBecomeActive(_ scene: UIScene) { + sceneLifeCycleDelegate.sceneDidBecomeActive(scene) } func sceneWillResignActive(_ scene: UIScene) { + sceneLifeCycleDelegate.sceneWillResignActive(scene) } - func sceneWillEnterForeground(_ scene: UIScene) { + func sceneDidEnterBackground(_ scene: UIScene) { + sceneLifeCycleDelegate.sceneDidEnterBackground(scene) } - func sceneDidEnterBackground(_ scene: UIScene) { + func scene( + _ scene: UIScene, + openURLContexts URLContexts: Set + ) { + sceneLifeCycleDelegate.scene(scene, openURLContexts: URLContexts) + } + + func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { + sceneLifeCycleDelegate.scene(scene, continue: userActivity) + } + + func windowScene( + _ windowScene: UIWindowScene, + performActionFor shortcutItem: UIApplicationShortcutItem, + completionHandler: @escaping (Bool) -> Void + ) { + sceneLifeCycleDelegate.windowScene( + windowScene, + performActionFor: shortcutItem, + completionHandler: completionHandler + ) } }