簡體   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