iOS SceneDelegate 适配

前言

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窗口管理我们可以不需要直接删掉就好了

  1. 删除掉info.plist中Application Scene Manifest选项
  2. 注释AppDelegate中相关Scene方法
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options

- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions
  1. 在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");
}
  1. SceneDelegate中的方法注释掉,或删除SceneDelegate文件

方式二
即要用iOS 13中新的SceneDelegate,又可以在iOS 13一下的设备中完美运行。那就添加版本判断,利用@available和__IPHONE_OS_VERSION_MIN_REQUIRED

  1. 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
  1. 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容