From 3a44b3d3ef37c2f7f252479da9a9e9919c540fa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans=20Kn=C3=B6chel?= Date: Thu, 15 Feb 2024 13:07:33 +0100 Subject: [PATCH] fix(ios): restore compatibility for Ti.App._resumeRestart() (#13989) * fix(ios): restore compatibility for Ti.App._resumeRestart() * chore: save session configuration, add warning for private API usage * chore: make sure to select the foreground/active scene, not only the first --- iphone/Classes/AppModule.m | 23 +++++++++++++++---- .../TitaniumKit/Sources/API/TiApp.h | 8 +++++++ .../TitaniumKit/Sources/API/TiApp.m | 8 +++++++ .../Sources/API/TiRootViewController.m | 9 +++++--- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/iphone/Classes/AppModule.m b/iphone/Classes/AppModule.m index 010b7bf3748..4c6ff86d0b6 100644 --- a/iphone/Classes/AppModule.m +++ b/iphone/Classes/AppModule.m @@ -48,9 +48,23 @@ - (void)_resumeRestart:(id)unused #ifndef TI_USE_AUTOLAYOUT [TiLayoutQueue resetQueue]; #endif + + // Get the currently active scene + UIScene *activeScene = nil; + for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) { + if (scene.activationState == UISceneActivationStateForegroundActive) { + activeScene = scene; + break; + } + } + + if (activeScene == nil) { + NSLog(@"[ERROR] No active scene connected - this may lead to an undefined behavior"); + } + /* Begin backgrounding simulation */ - [appDelegate applicationWillResignActive:app]; - [appDelegate applicationDidEnterBackground:app]; + [appDelegate sceneWillResignActive:activeScene]; + [appDelegate sceneDidEnterBackground:activeScene]; [appDelegate endBackgrounding]; /* End backgrounding simulation */ @@ -76,8 +90,9 @@ - (void)_resumeRestart:(id)unused /* Begin foregrounding simulation */ [appDelegate application:app didFinishLaunchingWithOptions:[appDelegate launchOptions]]; - [appDelegate applicationWillEnterForeground:app]; - [appDelegate applicationDidBecomeActive:app]; + [appDelegate scene:activeScene willConnectToSession:activeScene.session options:TiApp.app.connectionOptions]; + [appDelegate sceneWillEnterForeground:activeScene]; + [appDelegate sceneDidBecomeActive:activeScene]; /* End foregrounding simulation */ } diff --git a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.h b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.h index a9fe584766f..909962df8c5 100644 --- a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.h +++ b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.h @@ -26,6 +26,7 @@ KrollBridge *kjsBridge; NSMutableDictionary *launchOptions; + UISceneConnectionOptions *_connectionOptions; NSTimeInterval started; int32_t networkActivityCount; @@ -112,6 +113,13 @@ */ @property (nonatomic, readonly) NSDictionary *localNotification; +/** + Returns details for the last remote notification. + + Dictionary containing details about remote notification, or _nil_. + */ +@property (nonatomic, readonly) UISceneConnectionOptions *connectionOptions; + /** Returns the application's root view controller. */ diff --git a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.m b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.m index ec6803de5a6..bf4558f7789 100644 --- a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.m +++ b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.m @@ -48,6 +48,7 @@ @implementation TiApp @synthesize localNotification; @synthesize appBooted; @synthesize userAgent; +@synthesize connectionOptions; + (TiApp *)app { @@ -1062,6 +1063,7 @@ - (void)dealloc RELEASE_TO_NIL(queuedBootEvents); RELEASE_TO_NIL(_queuedApplicationSelectors); RELEASE_TO_NIL(_applicationDelegates); + RELEASE_TO_NIL(_connectionOptions); [super dealloc]; } @@ -1110,6 +1112,12 @@ - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session op // Initialize the launch options to be used by the client launchOptions = [[NSMutableDictionary alloc] init]; + // Retain connectionOptions for later use + if (_connectionOptions != connectionOptions) { + [_connectionOptions release]; // Release any existing object + _connectionOptions = [connectionOptions retain]; // Retain the new object + } + // If we have a APNS-UUID, assign it NSString *apnsUUID = [[NSUserDefaults standardUserDefaults] stringForKey:@"APNSRemoteDeviceUUID"]; if (apnsUUID != nil) { diff --git a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiRootViewController.m b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiRootViewController.m index 9f2ce2ff219..0d84e415f16 100644 --- a/iphone/TitaniumKit/TitaniumKit/Sources/API/TiRootViewController.m +++ b/iphone/TitaniumKit/TitaniumKit/Sources/API/TiRootViewController.m @@ -696,7 +696,8 @@ - (void)shutdownUi:(id)arg if (![TiSharedConfig defaultConfig].debugEnabled) { return; } - //FIRST DISMISS ALL MODAL WINDOWS + + // Dismiss all currently opened windows UIViewController *topVC = [self topPresentedController]; if (topVC != self) { UIViewController *presenter = [topVC presentingViewController]; @@ -706,7 +707,8 @@ - (void)shutdownUi:(id)arg }]; return; } - //At this point all modal stuff is done. Go ahead and clean up proxies. + + // Clean up proxies. NSArray *modalCopy = [modalWindows copy]; NSArray *windowCopy = [containedWindows copy]; @@ -725,7 +727,8 @@ - (void)shutdownUi:(id)arg [windowCopy release]; } - DebugLog(@"[INFO] UI SHUTDOWN COMPLETE. TRYING TO RESUME RESTART"); + DebugLog(@"[WARN] Calling the private `_restart()` API should not be done in production, as restarting an app is not a recommended native concept."); + if ([arg respondsToSelector:@selector(_resumeRestart:)]) { [arg performSelector:@selector(_resumeRestart:) withObject:nil]; } else {