iOS|iOS 13 SceneDelegate适配

Xcode 11新建工程
在Xcode 11 创建的工程,运行设备选择 iOS 13.0 以下的设备,运行应用时会出现黑屏现象。
原因:
【iOS|iOS 13 SceneDelegate适配】Xcode 11 默认是会创建通过 UIScene 管理多个 UIWindow 的应用,工程中除了 AppDelegate 外会多一个 SceneDelegate
AppDelegate和SceneDelegate这是iPadOS带来的新的多窗口支持的结果,并且有效地将应用程序委托的工作分成两部分。
也就是说在我们用多窗口开发iPadOS中,从iOS 13开始,您的应用代表应该:
设置应用程序期间所需的任何数据。
响应任何专注于应用的事件,例如与您共享的文件。
注册外部服务,例如推送通知。
配置您的初始场景。
相比之下,在iOS 13中的新顶级对象是一个UIWindowScene,场景代表可以处理应用程序用户界面的一个实例。因此,如果用户创建了两个显示您的应用程序的窗口,则您有两个场景,均由同一个应用程序委托支持。
这些场景旨在彼此独立工作。因此,您的应用程序不再移动到后台,而是单个场景执行 - 用户可以将一个移动到后台,同时保持另一个打开。
我们可以看下info.plist文件和工程项目文件的变化如图:

iOS|iOS 13 SceneDelegate适配
文章图片
image.png iOS|iOS 13 SceneDelegate适配
文章图片
image.png 适配方案一
如果我们不开发iPadOS多窗口APP,SceneDelegate窗口管理我们可以不需要直接删掉就好了。
删除掉info.plist中Application Scene Manifest选项,同时,文件SceneDelegate可删除可不删
相关代码注释掉:

#pragma mark - UISceneSession lifecycle- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; }- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { // Called when the user discards a scene session. // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. }

适配方案二
苹果文档如是说
In iOS 13 and later, use UISceneDelegate objects to respond to life-cycle events in a scene-based app.In iOS 12 and earlier, use the UIApplicationDelegate object to respond to life-cycle events.

不使用场景
当然,咱们也可以不使用场景.旧的不在info.plist中添加UIApplicationSceneManifest.或者是Xcode11以上的删除UIApplicationSceneManifest(Application Scene Manifest).然后就走的以前的Appdelegate的那些方法了.
如果要使用的话,记住需要判断一下版本.建议是用一个统一的类来处理这个问题.在内部转换成统一的通知名.方法等.方便处理
需要注意的点是,不使用场景的情况下别忘了在AppDelegate.h中添加window属性
@property (strong, nonatomic) UIWindow * window;

补充说明一下,如果不使用iPad的多窗口的话建议大家不要使用场景.

    推荐阅读