How to create different scenes with different views by code?

WWDC2020 videos said SwiftUI on Xcode12 can create and manage different scenes in an App, but we do not find out any API could do that. We try the method  of SwiftUI on Xcode11 to create new Window on Xcode 12 :

UIApplication.shared.requestSceneSessionActivation(nil, userActivity: nil, options: nil, errorHandler: nil) })

But it does not work as we expect. The code create a window of the same scene. If we set a different userActivity, SwiftUI have no method to set SceneDelegate.swift. It only has @UIApplicationDelegateAdaptor to set AppDelegate. 

So, I Wonder whether there is a convenient way to create a new Scene by new SwiftUI APIs.

The following code can only create Scenes with the same content view :

Code Block
@main struct test: App {
      let newWindowPublisher = NotificationCenter.default.publisher(for: Notification.Name("anotherScene"))
      var body: some Scene {
            WindowGroup {
                   ContentView()
                         .onReceive(newWindowPublish, perform: { info in
                            UIApplication.shared.requestSceneSessionActivation(nil, userActivity: nil, options: nil, errorHandler: nil) })
            }
       }
}


Answered by Nuix in 626205022
Code Block
@main
struct mindoApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
if options.userActivities.first?.activityType == "newWindow" {
let configuration = UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
configuration.delegateClass = SceneDelegate.self
return configuration
} else {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: TestView())
self.window = window
window.makeKeyAndVisible()
}
}
}


The following code is used to create a new scene/window

Code Block
UIApplication.shared.requestSceneSessionActivation(nil, userActivity: NSUserActivity(activityType: “newWindow"), options: nil, errorHandler: nil)


The TestView can be put into the second scene/window on iPadOS/macOS. But, the App crashes when closing the second scene/window:

Fatal error: Attempted to read an unowned reference but object 0x60000061d1c0 was already deallocated
Accepted Answer
Code Block
@main
struct mindoApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
if options.userActivities.first?.activityType == "newWindow" {
let configuration = UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
configuration.delegateClass = SceneDelegate.self
return configuration
} else {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: TestView())
self.window = window
window.makeKeyAndVisible()
}
}
}


The following code is used to create a new scene/window

Code Block
UIApplication.shared.requestSceneSessionActivation(nil, userActivity: NSUserActivity(activityType: “newWindow"), options: nil, errorHandler: nil)


The TestView can be put into the second scene/window on iPadOS/macOS. But, the App crashes when closing the second scene/window:

Fatal error: Attempted to read an unowned reference but object 0x60000061d1c0 was already deallocated
How to create different scenes with different views by code?
 
 
Q