如何在iPadOS多窗口(SceneDelegate)中获得rootViewController?

Fab*_*oft 8 ios13 xcode11 uiscenedelegate

我正在使用Xcode 11(beta3)并为iOS 13构建应用程序。在我的项目中,我创建了UIWindowSceneDelegate在Info.plist中声明它的委托方法。现在,我可以创建多个窗口(和UIScene)。

现在我已经没有单个窗口了,如何访问rootViewController?我需要它来获取对它所持有的对象和范围的一些引用。

在我的AppDelegate window is nil和ViewController(子视图控制器)实例中,我尝试使用,self.view.window.rootViewController但发现这viewDidLoad()还为时过早(我认为),并且该窗口仍为nil,可以在中工作viewDidAppear(),但是我不需要每次都进行此过程视图控制器出现的时间。

这种处理应用程序场景的新方法的最佳实践是什么?

这是我的AppDelegate:

func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        return true
    }

    func application(_ application: UIApplication,
                     configurationForConnecting connectingSceneSession: UISceneSession,
                     options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }
Run Code Online (Sandbox Code Playgroud)

我的SceneDelegate:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // yes it's empty, I'm using storyboard
    }
Run Code Online (Sandbox Code Playgroud)

小智 9

您可以使用以下方式访问连接的场景:

UIApplication.shared.connectedScenes
Run Code Online (Sandbox Code Playgroud)

根据Apple 文档

连接的场景是那些在内存中并可能进行活跃工作的场景。连接的场景可能在前景或背景中,也可能在屏幕上或屏幕外。

然后你可以遍历它们并尝试UIWindowScene从那里开始。

guard let windowScene = (scene as? UIWindowScene) else { return }
print(windowScene.windows) // This will print windows associated with the scene.
Run Code Online (Sandbox Code Playgroud)

另一方面,从视图控制器,您可以window通过以下方式访问view

self.view.window
Run Code Online (Sandbox Code Playgroud)


小智 5

现在,您有多个rootViewController,每个场景一个。首先,您必须回答使用时需要的那个。

可能您想获取当前活动场景的rootViewController之一,则可以使用以下命令:

        var rootVC:UIViewController? = nil
        if #available(iOS 13.0, *) {
            for scene in UIApplication.shared.connectedScenes {
                if scene.activationState == .foregroundActive {
                    rootVC = ((scene as? UIWindowScene)!.delegate as! UIWindowSceneDelegate).window!!.rootViewController
                    break
                }
            }
        } else {
            // Fallback on earlier versions
        }
Run Code Online (Sandbox Code Playgroud)