使用 UISceneDelegate 将旧 Xcode 项目迁移到新项目

Migrating old Xcode project to new one with UISceneDelegate

我有一个没有 UISceneDelegate 方法的旧 Xcode 项目。是否可以使用 UISceneDelegate 方法将旧 Xcode 项目迁移到新项目,但仍保持与 iOS 12 的兼容性?

如果可以,怎么做?因为我在 iOS 14 中看到很多错误,唯一的解决方法是使用 UISceneDelegate 方法。

编辑 1:

确保在呈现视图控制器的视图后查询 windowOrientation。通常在 viewDidLoad()viewWillAppear(_:) 中,view.windownil,检查这个 answer。只需检查 viewDidAppear(_:).

windowOrientation 的值

如果您在尝试以下定义之前访问此值时遇到一些问题

private var windowOrientation: UIInterfaceOrientation {
    if #available(iOS 13.0, *) {
        return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? .unknown
    } else {
        // Fallback on earlier versions
        return UIApplication.shared.statusBarOrientation
    }
}

我不确定您的应用是否使用多个 windows,但如果只有一个(因为您没有以编程方式创建任何 window),则以下定义​​应该可以正常工作。

var hasTopNotch: Bool {
    return UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0 > 20
}

原答案:

UISceneDelegate已在iOS 13.0中引入,因此无法与iOS 12兼容,您需要完全依赖UIApplicationDelegate。要在 for iOS 13.x 中支持 UISceneDelegate,您需要添加显式可用性检查以避免编译错误。

第 1 步:在 Info.plist

中添加场景清单

打开Info.plist作为Source Code并添加以下内容

<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>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
                <key>UISceneStoryboardFile</key>
                <string>Main</string>
            </dict>
        </array>
    </dict>
</dict>

第 2 步:使用以下内容创建 SceneDelegate.swift 文件

import UIKit
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let _ = (scene as? UIWindowScene) else { return }
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        // Called as the scene is being released by the system.
        // This occurs shortly after the scene enters the background, or when its session is discarded.
        // Release any resources associated with this scene that can be re-created the next time the scene connects.
        // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        // Called when the scene has moved from an inactive state to an active state.
        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
    }

    func sceneWillResignActive(_ scene: UIScene) {
        // 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).
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // Use this method to save data, release shared resources, and store enough scene-specific state information
        // to restore the scene back to its current state.
    }


}

第 3 步:更新 AppDelegate

  1. 添加 UISceneSession Lifecycle 方法。
// MARK: UISceneSession Lifecycle
@available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
@available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    // 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.
}

ii) 最后请参阅 Apple Documentation. You may refer to https://dev.to/kevinmaarek/add-a-scene-delegate-to-your-current-project-5on 以了解其他清理和设置任务。