SceneDelegate是为了支持iOS13之后iPadOS多窗口而推出的。Xcode 11 默认会创建通过 UIScene 管理多个 UIWindow 的应用,工程中除了 AppDelegate 外会多一个 SceneDelegate。AppDelegate.h不再有window属性,window属性被定义在了SceneDelegate.h中,SceneDelegate负责原属AppDelegate的UI生命周期部分的职责。
对于这个特性的适配通常有以下两种做法:
一、不需要多窗口(multiple windows)
如果需要支持iOS 13 及之前多个版本的iOS,且又不需要多个窗口的功能,可以直接删除以下内容:
1.info.plist文件中的Application Scene Manifest的配置数据;
2.AppDelegate中关于Scene的代理方法;
3.SceneDelegate的类
如果使用纯代码来实现显示界面,需要在AppDelegate.h中手动添加window属性,添加以下代码即可:
//// AppDelegate.h中
@property (strong, nonatomic) UIWindow *window;
//// AppDelegate.m中
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.window setBackgroundColor:[UIColor whiteColor]];
ViewController *con = [[ViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:con];
[self.window setRootViewController:nav];
[self.window makeKeyAndVisible];
return YES;
}
二、支持多窗口(multiple windows)
iOS 13项目info.plist中的配置项Application Scene Manifest是针对iPad multiple windows功能推出的。在保留Application Scene Manifest配置项不予删除时(其中,项目是否支持多窗口功能是个可勾选项),AppDelegate的生命周期方法不再起作用,需要在SceneDelegate中使用UIScene提供的生命周期方法,并且需要针对 iOS 13 需要在Scene中配置和 iOS 13 以下在AppDelegate中做两套配置。
下面是纯代码实现界面显示的代码:
//// AppDelegate.m中
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if (@available(iOS 13.0, *)) {
} else {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.window setBackgroundColor:[UIColor whiteColor]];
ViewController *con = [[ViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:con];
[self.window setRootViewController:nav];
[self.window makeKeyAndVisible];
}
return YES;
}
//// SceneDelegate.m中
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
//在这里手动创建新的window
if (@available(iOS 13.0, *)) {
UIWindowScene *windowScene = (UIWindowScene *)scene;
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.window setWindowScene:windowScene];
[self.window setBackgroundColor:[UIColor whiteColor]];
ViewController *con = [[ViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:con];
[self.window setRootViewController:nav];
[self.window makeKeyAndVisible];
}
}
AppDelegate与SceneDelegate的职责划分:
iOS13之前,Appdelegate的职责全权处理App生命周期和UI生命周期;
iOS13之后,Appdelegate的职责是:1. 处理 App 生命周期;2. 新的 Scene Session 生命周期。SceneDelegate的职责是:所有UI生命周期。
SceneDelegate相关页面图片:
参考文档: