Skip to content

Commit

Permalink
fix(ios): restore compatibility for Ti.App._resumeRestart() (#13989)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
hansemannn authored Feb 15, 2024
1 parent 047b21b commit 3a44b3d
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 7 deletions.
23 changes: 19 additions & 4 deletions iphone/Classes/AppModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand All @@ -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 */
}

Expand Down
8 changes: 8 additions & 0 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
KrollBridge *kjsBridge;

NSMutableDictionary *launchOptions;
UISceneConnectionOptions *_connectionOptions;
NSTimeInterval started;

int32_t networkActivityCount;
Expand Down Expand Up @@ -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.
*/
Expand Down
8 changes: 8 additions & 0 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ @implementation TiApp
@synthesize localNotification;
@synthesize appBooted;
@synthesize userAgent;
@synthesize connectionOptions;

+ (TiApp *)app
{
Expand Down Expand Up @@ -1062,6 +1063,7 @@ - (void)dealloc
RELEASE_TO_NIL(queuedBootEvents);
RELEASE_TO_NIL(_queuedApplicationSelectors);
RELEASE_TO_NIL(_applicationDelegates);
RELEASE_TO_NIL(_connectionOptions);

[super dealloc];
}
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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];

Expand All @@ -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 {
Expand Down

0 comments on commit 3a44b3d

Please sign in to comment.