1、创建项目
在Xocde12上我们创建swift项目的时候Interface有两种选择:SwiftUI 和 Storyboard。其中SwiftUI只支持iOS13以上的系统,所以如果需要面向iOS13以下系统则无法使用。那么只能使用Storyboard,LifeCycle使用UIKit App Delegate。但是Xocde12默认为我们创建的项目如下:
这时候我们无法在iOS13以下系统上运行,会提示iOS Deployment Target过高。
查看在build setting中的iOS Deployment Target,发现默认是iOS14.x,我们将它改到iOS13以下系统(如12.3)。
2、解决xxx is only available in iOS 13.0 or newer
降级iOS Deployment Target后再编译后发现项目报了大量的错误,错误类似:
'ConnectionOptions' is only available in iOS 13.0 or newer
'UIScene' is only available in iOS 13.0 or newer
'UISceneConfiguration' is only available in iOS 13.0 or newer
'UISceneSession' is only available in iOS 13.0 or newer
'UIWindowScene' is only available in iOS 13.0 or newer
...
这是因为默认创建的项目中在AppDelegate和SceneDelegate中使用了UIScene等只有iOS13以上系统才支持的功能。
解决方法是添加 @available(iOS 13.0, *) 标识,比如AppDelegate:
import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } // 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. } } 复制代码
为后两个函数添加这个标识,这样只有在iOS13.0以上系统才会加载。而SceneDelegate则需要为整个类添加这个标识:
import UIKit @available(iOS 13.0, *) class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? ... } 复制代码
这样再编译就不会报错了,在iOS 13.0以上系统依然可以正常运行。
3、iOS13以下系统黑屏
解决上面的问题后,在iOS13以下系统上可以运行了,但是运行后发现黑屏。这是因为AppDelegate将管理整个App生命周期的任务委托给了SceneDelegate,所以window属性移到了SceneDelegate下,如下:
import UIKit @available(iOS 13.0, *) class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? ... } 复制代码
但是SceneDelegate在iOS13以下系统并不加载,所以没有window属性自然就黑屏了。解决方法就是在AppDelegate中也添加一个window属性,如下:
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. return true } // MARK: UISceneSession Lifecycle ... } 复制代码
这样再运行就可以看到正常页面了。
这样之后:
iOS13以下版本的时候,window就走AppDelegate这里,不会黑屏;
iOS13或以上版本的时候,window就走SceneDelegate(被委托人)这里,不会黑屏;