xcode11后增加SceneDelegate、创建新项目删除SceneDelegate

不使用sceneDelegate、Main.storyboard

1、给AppDelegate添加window属性,并初始化window【Swift版本代码参考:swift纯代码新建项目
OC代码如下:
@interface AppDelegate : UIResponder
@property (nonatomic, strong) UIWindow *window;
@end

@implementation AppDelegate

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    // 创建 UIWindow 并设置大小为整个设备屏幕
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    // 创建并设置根视图控制器
    ViewController *rootViewController = [[ViewController alloc] init];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
    self.window.rootViewController = navigationController;
    // 显示窗口
    [self.window makeKeyAndVisible];

    return YES;
    }

2、删除掉AppDelegate中的两个关于SceneDelegate的两个协议方法
3、删除掉Info.plist中的Applection Scene Manifest 字段、Main storyboad file base name 字段
4、删除掉SceneDelegate文件、Main.storyboard文件
5、在AppDelegate中把之前的几个代理方法些回来

背景

xcode 11 对应着 iOS 13.0
使用xcode 11 之后的版本创建新项目,会跟之前有些不同
比如:

  • 新增 SceneDelegate 文件
  • AppDelegate 文件结果也发生了变化
    • AppDelegate 头文件中没有了 window 属性,而是在 SceneDelegate 的头文件中
    • AppDelegate 头文件中关于应用 UI 生命周期的协议方法不见了

可见 AppDelegate 不再管理 window 而是交给了 SceneDelegate,xcode 11 之前是 AppDelegate 管理应用生命周期和应用 UI 生命周期,Xcode 11 之后是 AppDelegate 管理应用生命周期和 SceneDelegate 的声明周期,将应用程序 UI 生命周期交给 SceneDelegate 管理,这也就是为什么 window 属性放置在了 SceneDelegate 头文件中。

处理理念

SceneDelegate 的作用是为了使应用在 iPad 上设置多个 scene,可以理解为分层,要是不想分屏,可以不使用 SceneDelegate,值得注意的是该分屏功能只适用于 iPad 上运行,iPhone 暂时不支持分屏。效果如下图:
image

这样思路就清晰了:
首先开发的应用App要不要支持iPad,如果要支持那么要不要支持分屏功能。
如果不用支持iPad,既然这个分屏功能在iPhone上也用不了,那么就是两种选择,要么把一些新增的改变全部删掉还原,用以前AppDelegate那一套。第二种选择就是使用SceneDelegate,但是这里又会有一个选择,那就是SceneDelegate是在iOS13之后才支持的,如果应用App需要支持iOS13以下的手机,那么还不能只使用SceneDelegate这么简单,需要同时支持AppDelegate 和 SceneDelegate。分类如下:

  • 要使用分屏功能
  • 不要使用分屏功能
    • 开发的 App 不需要支持 iOS 13 以下设备
    • 开发的 App 需要支持 iOS 13 以下的设备
      • 使用 SceneDelegate
      • 不使用 SceneDelegate

要使用分屏

本文不涉及此内容详细说明,只记录一些简单的信息

1、在项目配置中开启分屏选项
image
2、在项目的info文件中开启
image
3、相关信息的简介
image

单纯使用SceneDelegate

如果不需要支持 iOS 13 以下的设备,那么单纯使用SceneDelegate就行了

1、AppDelegate中多出来的两个SceneDelegate的生命周期的代理方法

//1.如果没有在APP的Info.plist文件中包含scene的配置数据,或者要动态更改场景配置数据,需要实现此方法。 UIKit会在创建新scene前调用此方法。
//参数options是一个UISceneConnectionOptions类,官方解释:它包含了为什么要创建一个新的scene的信息。根据参数信息判断是否要创建一个新的scene
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
    NSLog(@"1");
    // 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];
}
//方法会返回一个UISceneConfiguration对象,其包含其中包含场景详细信息,包括要创建的场景类型,用于管理场景的委托对象以及包含要显示的初始视图控制器的情节提要。 如果未实现此方法,则必须在应用程序的Info.plist文件中提供场景配置数据。
//总结下:默认在info.plist中进行了配置, 不用实现该方法也没有关系。如果没有配置就需要实现这个方法并返回一个UISceneConfiguration对象。
//在分屏中关闭其中一个或多个scene时候回调用。
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)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.
    NSLog(@"2");
}

2、手动创建新的window

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
   //在这里手动创建新的window
   if (scene) {
       UIWindowScene *windowScene = (UIWindowScene *)scene;
       self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
       self.window.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
       self.window.rootViewController = [ViewController new];
       [self.window makeKeyAndVisible];
   }
}

3、SceneDelegate中的生命周期代理方法

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    NSLog(@"场景加载完成");
}
- (void)sceneDidDisconnect:(UIScene *)scene {
    NSLog(@"场景已经断开连接");
}
- (void)sceneDidBecomeActive:(UIScene *)scene {
    NSLog(@"已经从后台进入前台");
}
- (void)sceneWillResignActive:(UIScene *)scene {
    NSLog(@"即将从前台进入后台");
}
- (void)sceneWillEnterForeground:(UIScene *)scene {
    NSLog(@"即将从后台进入前台");
}
- (void)sceneDidEnterBackground:(UIScene *)scene {
    NSLog(@"已经从前台进入后台");
}

单纯使用AppDelegate

如果需要支持 iOS 13 以下的设备,但是又不想使用 SceneDelegate,那么可以将新增的文件和相关配置统统删除掉,使用之前的AppDelegate就行了

1、给AppDelegate添加window属性
2、删除掉AppDelegate中的两个关于SceneDelegate的两个协议方法
3、删除掉Info.plist中的Applection Scene Manifest 字段
4、删除掉SceneDelegate文件
5、在AppDelegate中把之前的几个代理方法些回来

- (void)applicationDidFinishLaunching:(UIApplication *)application;
- (void)applicationWillResignActive:(UIApplication *)application;
- (void)applicationDidEnterBackground:(UIApplication *)application API_AVAILABLE(ios(4.0));
- (void)applicationWillEnterForeground:(UIApplication *)application API_AVAILABLE(ios(4.0));
- (void)applicationDidBecomeActive:(UIApplication *)application;
- (void)applicationWillTerminate:(UIApplication *)application;

SceneDelegate 和 AppDelegate 同时使用

如果需要支持 iOS 13 以下的设备,又想使用 SceneDelegate

这里有一点需要注意,如果是iOS13及以上,那么就按照新建项目时提供的默认方式进行进行了。
如果是iOS13以下,那么Appdelegate中只是需要增加window的创建,应用程序的UI生命周期依然还是放在SceneDelegate中管理,不可能AppDelegate和SceneDelegate同时来管理。
image

参考文章:
https://www.jianshu.com/p/5922f3e7f8b6
https://blog.csdn.net/baidu_40537062/article/details/106647783
https://blog.csdn.net/m0_37681833/article/details/103741827
https://juejin.cn/post/6916379319820353550
https://my.oschina.net/u/4354993/blog/3309895

posted @ 2022-01-21 16:07  码出境界  阅读(1086)  评论(0编辑  收藏  举报