SceneDelegate 在 Swift Storyboard 项目中的使用

在 Xcode 11以后,新建采用Storyboard 的Swift项目,会自动生成一个 SceneDelegate 文件。 如果使用这个默认生成文件,iOS版本就需要保持在13以上。当然,也可以删除这个文件,重新只使用AppDeleagte,回到以前的样子。

UIScene 是 iOS13以后,提出的一个新类型,为显示App界面对象,并可以实现多场景界面。在UIKit中,使用 UIWindowScene 替代 UIScene, 用于访问其属性和方法。而且自身的变化,则是使用一个遵守UISceneDelegate的对象进行管理。至于UIWindowScene,就是使用一个遵守UIWindowSceneDelegate的对象进行管理。

UIWindowScene 继承 UIScene, UIWindowSceneDelegate 继承 UISceneDelegate。

在创建项目时自动生成的 SceneDelegate类,则就是一个遵守UIWindowSceneDelegate的对象,在这里,就可以观察到Scene的一些变化,并根据需要添加自定义的设置。

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let _ = (scene as? UIWindowScene) else { return }
        print("Will Connect To Session")
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        print("Scene Did Disconnect")
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        print("Did Become Active")
    }

    func sceneWillResignActive(_ scene: UIScene) {
        print("Will Resign Active")
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        print("Will Enter Foreground")
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        print("Did Enter Background")
    }
}

window 属性,scene 使用的主窗口。

其他方法,则是类似于以前在 Appdelegate 管理的生命周期,不过现在是和scene有关。

  • 将要连接 willConnectTo 和 已经失去连接 did Disconnect
  • 将要进入前台 willEnterForeground 和 已经活动状态 didBecomeActive
  • 将要进入非活动苔 willResignActive 和 已经进入后台 didEnterBackground

现在在相应方法的内部,添加打印信息,来验证一下相关方法的调用时机。

  1. 打开App
Will Connect To Session
Will Enter Foreground
Did Become Active
  1. 退到后台
Will Resign Active


Did Enter Background
  1. 点击app,重新进入前台
Will Enter Foreground
Did Become Active

  1. 切换App,再回来
Will Resign Active


Did Become Active

  1. 结束App
Will Resign Active


Scene Did Disconnect

可见,加入scene之后,它的变化已经和app的生命周期变化关联起来,与生命周期相关的管理操作,在iOS13以后,都交给了SceneDeleagate。

项目入口

默认情况下,项目采用 Main.storyboard 的方式创建启动app,这种情况下是不需要任何设置的,window 和 scene 就可以建立关联,启动 Main.storybaord 的初始 view controller。

但是,如果采用代码方式创建入口,然后关联scece 和 window,就要手动设置了。

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let winScene = (scene as? UIWindowScene) else { return }
    let win = UIWindow(windowScene: winScene)
    let vc = UIViewController()
    win.rootViewController = vc
    self.window = win
    window!.makeKeyAndVisible()
}

这里手动配置与scene关联的window,以及配置了 window的 root view controller。

不使用 SceneDelegate

有些情况,新建的项目并不喜欢使用默认生成的SceneDelegate,而是想回到以前使用AppDelegate 管理App生命周期的情况,实现起来也不难。

对于使用Storyboard作为入口的项目:

  1. 删除项目的SceneDelegate.swift文件。
  2. 在AppDelegate类中添加 var window: UIWindow?属性。
  3. 在 Target 的 Info 选项中,删除 Application Scene Manifestkey 的内容。

重新run 一下,就已经可以了。

另外说一下这个 Application Scene Manifestkey,这个就是项目中使用Scene的配置项,新建项目会默认生成,且多scene,还有scene的配置信息也在这里。

至于纯代码创建入口,和之前的操作是一样的,不再叙述。

总结

SceneDelegate 的出现,分离了 AppDelegate 的一部分职责功能,这里主要是一些类似生命周期相关的职责功能,以前关于生命周期的App配置,现在转到了SceneDelegate中处理。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYhbUsR2' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片