繁体   English   中英

支持 iOS 12 和 13 时的 AppDelegate 和 SceneDelegate

[英]AppDelegate and SceneDelegate when supporting iOS 12 and 13

我需要支持 iOS 12 和 iOS 13。

我应该在AppDelegateSceneDelegate之间复制代码吗?

例如:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    let window = UIWindow(windowScene: windowScene)

    window.rootViewController = HomeViewController()
    window.makeKeyAndVisible()

    self.window = window
}

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    let window = UIWindow(frame: UIScreen.main.bounds)
    window.rootViewController = HomeViewController()
    window.makeKeyAndVisible()

    self.window = window

    return true
}

如果我不这样做,在 1 版本中我最终会出现黑屏,但如果我这样做并在HomeViewControllerviewDidLoad方法中打印,我可以看到它被调用了两次。

我更新了我的didFinishLaunchingWithOptions并且我可以在iOS13中看到它仍然被调用了两次。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    guard #available(iOS 12, *) else { return true }

    let window = UIWindow(frame: UIScreen.main.bounds)
    window.rootViewController = HomeViewController()
    window.makeKeyAndVisible()

    self.window = window

    return true
}

您确实需要复制代码,但您需要确保它仅在正确的系统上运行。 在 iOS 13 中,您不希望应用程序委托didFinishLaunching主体代码运行,因此使用可用性检查来阻止它。 同样,使用可用性从 iOS 12 中隐藏 window 场景内容。

这是在 iOS 12 和 iOS 13 上正确运行的解决方案的基本草图:

AppDelegate.Swift

import UIKit
@UIApplicationMain
class AppDelegate : UIResponder, UIApplicationDelegate {
    var window : UIWindow?
    func application(_ application: UIApplication,
        didFinishLaunchingWithOptions 
        launchOptions: [UIApplication.LaunchOptionsKey : Any]?)
        -> Bool {
            if #available(iOS 13, *) {
                // do only pure app launch stuff, not interface stuff
            } else {
                self.window = UIWindow()
                let vc = ViewController()
                self.window!.rootViewController = vc
                self.window!.makeKeyAndVisible()
                self.window!.backgroundColor = .red
            }
            return true
    }
}

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) {
            if let windowScene = scene as? UIWindowScene {
                self.window = UIWindow(windowScene: windowScene) 
                let vc = ViewController()                      
                self.window!.rootViewController = vc             
                self.window!.makeKeyAndVisible()                 
                self.window!.backgroundColor = .red
            }
    }
}

ViewController.swift

import UIKit
class ViewController : UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        print("view did load")
        self.view.backgroundColor = .green
    }
}

请注意,处理其他重复项(例如应用程序激活)要简单得多,因为如果您支持 window 场景,则不会在 iOS 12 上调用应用程序委托方法。所以问题仅限于这种情况,即您有 Z05B8C735296FBF2FZDE4C1 / 根视图 controller 在启动时执行的操作(例如,没有情节提要)。

Xcode 11.* 和 Swift 5.*

按照下面给出的步骤,您的代码将适用于 iOS 12 和 iOS 13 -

  1. 从 info.plist 文件中删除场景清单
  2. 移除场景委托
  3. 在 AppDelegate 中添加 window 属性
  4. 从 AppDelegate 中移除所有与场景相关的方法(主要是 2 种方法)

希望这对某人有用。 快乐编码

这是我的工作。

@提供了 SceneDelegate.swift

As the SceneDelegate class is only available on iOS 13 and above, we have to tell the compiler to only include the class for iOS 13 and above. 为此,我们将在 SceneDelegate class 声明的正上方添加这一行“@available(iOS 13.0, *)”,如下所示:

import UIKit

@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
//...
}

@在 AppDelegate.swift 中提供一些方法

接下来在AppDelegate.swift中新增两个方法,仅支持iOS 13及以上。 我们还将在它们之上添加相同的 @available(iOS 13.0, *) :

// AppDelegate.swift

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

将 window 添加回 AppDelegate

如果您现在构建并运行您的应用程序,您将看到黑屏,因为没有初始化 UIWindow。

在 iOS 12 和更早版本中,总是有一个 var window: UIWindow? 位于 AppDelegate.swft 顶部的变量。 iOS 13 已将此变量移至 SceneDelegate.swift,现在我们将将此变量添加回 AppDelegate。

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
     
    var window: UIWindow?
  
    // ...
}

现在在 iOS 12 设备上构建并运行您的应用程序,它可以工作了!

I guess Apple really wants iOS developers to adopt and focus on iOS 13, to the extent that they don't mind breaking support for iOS 12 and older with default settings in Xcode.

If you are lazy to do these step manually every time, you can also download Xcode 10.3 in the Apple's developer download portal (require sign in with your Apple ID), create a new Xcode project using it, and then edit it using Xcode 11.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM