今是昨非

今是昨非

日出江花红胜火,春来江水绿如蓝

iOS 刪除新創建項目中的 SceneDelegate

iOS 刪除新創建項目中的 SceneDelegate#

背景#

Xcode 11 之後新建工程,默認為有 SceneDelegate,但是 SceneDelegate 是從 iOS 13 之後才有的,如果最低兼容版本到 iOS 13 以下,需要怎麼做呢?

過程#

首先來看一下,SceneDelegate 是什麼,為什麼會有 SceneDelegate

官方說明:

A UISceneSession object manages a unique runtime instance of your scene. When the user adds a new scene to your app, or when you request one programmatically, the system creates a session object to track that scene. The session contains a unique identifier and the configuration details of the scene. UIKit maintains the session information for the lifetime of the scene itself, destroying the session in response to the user closing the scene in the app switcher.
You do not create session objects directly. UIKit creates sessions in response to user interactions with your app. You can also ask UIKit to create a new scene and session programmatically by calling the requestSceneSessionActivation(_:userActivity:options:errorHandler:) method of UIApplication. UIKit initializes the session with default configuration data based on the contents of your app's Info.plist file.

翻譯解釋:

在 iOS 13(及以後版本)上,SceneDelegate 將負責 AppDelegate 的某些功能。 最重要的是,window(窗口)的概念已被 scene(場景)的概念所替代。 一個應用程序可以具有不止一個場景,而一個場景現在可以作為您應用程序的用戶界面和內容的載體(背景)。

Xcode 11 新創建的項目涉及到 SceneDelegate 的地方如下:

  1. AppDelegate 類中兩個 “scene sessions” 方法:application (:configurationForConnecting:options:) 和 application (:didDiscardSceneSessions:)
  2. 一個 SceneDelegate 類,其中包括生命週期事件,例如 active,resign 和 disconnect。
  3. Info.plist 文件中提供了”Application Scene Manifest“配置項,用於配置 App 的場景,包括它們的場景配置名,delegate 類名和 storyboard 入口

那不需要 SceneDelegate,要怎麼處理?
兩種方法,
a. 一種是直接把 SceneDelegate 相關的刪除
b. 另外一種則是根據系統版本判斷兼容

方法一:刪除 SceneDelegate

  1. 把 AppDelegate 中 UISceneSession Lifecycle 的兩個代理方法刪除,添加 window 屬性,在 application:didFinishLaunchingWithOptions: 方法中初始化 window,設置根視圖
  2. 刪除 SceneDelegate 文件
  3. 選中 target,切換到 info,刪除 Application Scene Manifest 這行

/// AppDelegate.Swift

import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.backgroundColor = UIColor.white
        
        self.window?.rootViewController = HXBaseViewController()
        self.window?.makeKeyAndVisible()
        
        return true
    }

}

WeCom20210421-115403@2x.png

方法二:根據系統版本判斷兼容,但是這種方法要注意,iOS 13 之後有些程序狀態的處理要在 SeceneDelegate 中

  1. 首先在 SceneDelegate 中加入 @available (iOS 13, *) 的聲明,
  2. 然後把 AppDelgate 中 UISceneSession Lifecycle 的兩個代理方法寫到單獨的 Extension 中,然後聲明 @avaiable (iOS 13, *),
  3. AppDelegate 的啟動方法中也需要修改,編譯即可

// SceneDelegate.swift
import UIKit

@available(iOS 13, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    xxx
}


class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        if #available(iOS 13.0, *) {
            // 不需要處理,走SceneDelegate
        }
        else {
            // 初始化UIWindow
            window = UIWindow.init()
            window?.frame = UIScreen.main.bounds
            window?.makeKeyAndVisible()
            window?.rootViewController = UIStoryboard.init(name: "Main", bundle: nil).instantiateInitialViewController()
        }
        return true
    }
}



@available(iOS 13, *)
extension AppDelegate {
    // MARK: UISceneSession Lifecycle

    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)
    }

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

參考#

iOS13 Scene Delegate 詳解
iOS 13 SceneDelegate 適配

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。