迁移到基于 UIScene 生命周期

核心必需步骤(Key Necessary Steps)

1. 修改 Info.plist

在 Info.plist 中添加 UIScene Configuration:

    <key>UIApplicationSceneManifest</key>
    <dict>
        <key>UIApplicationSupportsMultipleScenes</key>
        <false/>
        <key>UISceneConfigurations</key>
        <dict>
            <key>UIWindowSceneSessionRoleApplication</key>
            <array>
                <dict>
                    <key>UISceneConfigurationName</key>
                    <string>Default Configuration</string>
                    <key>UISceneDelegateClassName</key>
                    <string>ZZFlashAirShareSceneDelegate</string>
                    <key>UISceneStoryboardFile</key>
                    <string>Main</string>
                </dict>
            </array>
        </dict>
    </dict>

如果没有使用 storboadfile的话,其中的 UISceneStoryboardFile 可以删除。
如果要支持多窗口的话,可以设置 UIApplicationSupportsMultipleScenestrue
如果原本使用了 UIMainStoryboardFile, 那么需要删除该键值。

2. AppDelegate 改造

实现 iOS13 后新增的AppDelegate协议:

#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<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.
}

代码中 UISceneConfigurationnameInfo.plist 中的 UISceneConfigurationName 对应。

3. 新加 SceneDelegate 文件

新建文件 YourSceneDelegate, objc 的话:

@interface YourSceneDelegate : UIResponder<UIWindowSceneDelegate>
@property (strong, nonatomic) UIWindow * window;

@end

注意 AppDelegate 中已经没有 window 属性,该属性在 SceneDelegate 中。

实现文件中依次实现:

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {

    // 如果手动添加ViewController的话
    if (self.window == nil) {
        self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
    }
    YourMainViewController *mainVC = [[YourViewController alloc] initWithNibName:nil bundle:nil];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:mainVC];
    self.window.rootViewController = navController;
    [self.window makeKeyAndVisible];

}


- (void)sceneDidDisconnect:(UIScene *)scene {

}


- (void)sceneDidBecomeActive:(UIScene *)scene {

}


- (void)sceneWillResignActive:(UIScene *)scene {
    // Called when the scene will move from an active state to an inactive state.
    // This may occur due to temporary interruptions (ex. an incoming phone call).
}


- (void)sceneWillEnterForeground:(UIScene *)scene {

}


- (void)sceneDidEnterBackground:(UIScene *)scene {

}

可以发现第一个协议中替代了 AppDelegate 中 application:didFinishLaunchingWithOptions: 的功能。
接下来的几个协议中,将在 AppDelegate 中对应的协议实现根据项目情况“复制”过来。

AppDelegate方法 SceneDelegate替代方法 处理场景
applicationWillEnterForeground sceneWillEnterForeground 场景即将进入前台
applicationDidBecomeActive sceneDidBecomeActive 场景激活状态切换
applicationWillResignActive sceneWillResignActive 场景即将进入非活动状态
applicationDidEnterBackground sceneDidEnterBackground 场景进入后台

4. 修改 Appdelegate 中的 window 属性

如果曾经使用过 AppDelegate 中的 window属性,那么需要更新。可以参考:

UIWindow *keywindow = self.view.window;

参考

Comments