I have an iPad app in which I'm starting to support multiple windows / scenes. I have one main window type, let's say MainScene
, and at least one secondary window type for opening specific types of content, say DetailScene
.
I have not declared my scene types in Info.plist
. I have implemented application:configurationForConnectingSceneSession:options:
like this:
-(UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options
{
NSUserActivity *activity = options.userActivities.anyObject;
NSString *activityType = activity.activityType;
if ([activityType isEqualToString:@"detailType"])
return [DetailSceneDelegate makeSceneConfiguration];
return [MainSceneDelegate makeSceneConfiguration];
}
Say I perform these steps:
configurationForConnectingSceneSession
, and the activity type is nil
so it returns a MainScene
.configurationForConnectingSceneSession
returns a DetailScene
. Creating the new scene looks like this:NSUserActivity *activity = [[NSUserActivity alloc] initWithActivityType:@"detailType"];
activity.userInfo = @{@"content_id": @(contentRowId)};
[[UIApplication sharedApplication] requestSceneSessionActivation:nil userActivity:activity options:nil errorHandler:nil];
At this point I do not get a call to configurationForConnectingSceneSession
. I get the detail scene back, restored from its user activity, with calls straight to DetailSceneDelegate
.
My question: how do I control what scene gets restored in this situation? I want my main scene to come back.
Messages and Mail and Notes all do this. If you open Messages and drag a conversation out into a new window, you get a window for that conversation with a Done button in the corner that will dismiss the window. If you perform my steps above with Messages, you will relaunch to the full Messages view. Are they converting the detail view to a main view on the fly? Or is there a way to tell the system that the detail scene is secondary and should not be restored first, or that I should get asked what I want to restore via configurationForConnectingSceneSession
? Or something else?
I cross-posted this to the Apple Developer forums and got an answer from a Framework Engineer. The answer is UISceneActivationConditions
, set as a property on UIScene
. Set the canActivateForTargetContentIdentifierPredicate
to always return NO
:
scene.activationConditions.canActivateForTargetContentIdentifierPredicate = [NSPredicate predicateWithValue:NO];
I do this in my implementation of scene:willConnectToSession:options:
in my UIWindowSceneDelegate
implementation.
As of current writing, on Xcode 13.2 and iOS 15.2 simulator, it works if the second launch (step 4 above) is via tapping the app icon, but not when it's via building and running in Xcode. I may file a feedback on this.