前言
xcode11创建项目新增SceneDelegate文件,AppDelegate文件结构也发生变化,在AppDelegate.h文件中没有了window属性,而是在SceneDelegate.h中,可见AppDelegate不管理window而是交给SceneDelegate
AppDelegate和SceneDelegate这是iPadOS带来的新的多窗口支持的结果,并且有效地将应用程序委托的工作分成两部分
变化
iOS13之前:在app状态发生改变时,UIKit 框架会发送通知到UIApplicationDelegate 对象上;
iOS13及其以后,在app状态发生改变时,UIKit 会优先发送通知到 SceneDelegate对象上;
- UIApplicationDelegate对象上只剩下三个函数:
加载完成:didFinishLaunchingWithOptions
配置将要连接的场景:configurationForConnectingSceneSession
丢弃场景对象之后:didDiscardSceneSessions
- SceneDelegate接管了所有的 app 过渡函数和场景的连接:
将要连接场景:willConnectToSession
已连接场景:sceneDidDisconnect
场景已经处于活动状态:sceneDidBecomeActive
场景将要处于非活动状态:sceneWillResignActive
场景将要进入前台:sceneWillEnterForeground
场景已经进入后台:sceneDidEnterBackground
注意
iOS13 之后不代表一定有分屏,也不代表 iPhone 可以使用分屏功能,当前仍然只有 iPad 可以使用分屏功能;
开启分屏需要勾选Supports multiple windows并进行配置和支持,iPad 开发在此不讨论,所以不会展开分屏功能的开发细节;
适配
方式一
如果我们不开发iPadOS多窗口APP,SceneDelegate窗口管理我们可以不需要直接删掉就好了
- 删除掉info.plist中Application Scene Manifest选项
- 注释AppDelegate中相关Scene方法
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions
- 在AppDelegate 中添加window 属性,并在didFinishLaunchingWithOptions中创建window
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = [ViewController new];
[self.window makeKeyAndVisible];
return YES;
}
4.Appdelegate中增加APP状态的回调方法
-(void)applicationWillResignActive:(UIApplication *)application{
NSLog(@"applicationWillResignActive");
}
- (void)applicationDidBecomeActive:(UIApplication *)application{
NSLog(@"applicationDidBecomeActive");
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(@"applicationWillEnterForeground");
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(@"applicationDidEnterBackground");
}
- SceneDelegate中的方法注释掉,或删除SceneDelegate文件
方式二
即要用iOS 13中新的SceneDelegate,又可以在iOS 13一下的设备中完美运行。那就添加版本判断,利用@available和__IPHONE_OS_VERSION_MIN_REQUIRED
- Appdelegate didFinishLaunchingWithOptions中判断版本
if (@available(iOS 13.0, *)) {
}else{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = [ViewController new];
[self.window makeKeyAndVisible];
}
return YES;
2.Appdelegate Scene相关方法适配
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_13_0
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13.0)){
if (@available(iOS 13.0, *)) {
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
} else {
return nil;
// Fallback on earlier versions
}
}
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions API_AVAILABLE(ios(13.0)){
}
#endif
- SceneDelegate willConnectToSession适配
if (@available(iOS 13.0, *)) {
}else{
UIWindowScene *windowScene = (UIWindowScene *)scene;
self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
self.window.frame = windowScene.coordinateSpace.bounds;
self.window.rootViewController = [ViewController new];
[self.window makeKeyWindow];
[self.window makeKeyAndVisible];
}
参考文章
https://blog.csdn.net/weixin_44060108/article/details/103629392
https://blog.csdn.net/qq_36724920/article/details/103887518