即使在添加 SceneDelegate 并更新 Info.plist 之后,Xcode 11 上的 iOS13 黑屏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/58207755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS13 on Xcode 11 Black screen even after adding SceneDelegate and updating Info.plist
提问by Kris RaduhaSt
I am currently getting a blank screen with Xcode 11, Target iOS 13.0 (the app works fine with all below versions iOS 12.1 till 12.4), I want to make my App work for both iOS users above 12.1 and also 13.0 currently getting blank screen despite adding the below SceneDelegate to my existing project and
我目前正在使用 Xcode 11 获得空白屏幕,目标 iOS 13.0(该应用程序适用于所有低于 iOS 12.1 到 12.4 的版本),我想让我的应用程序同时适用于 12.1 和 13.0 以上的 iOS 用户,尽管目前仍然获得空白屏幕将下面的 SceneDelegate 添加到我现有的项目和
adding App Manifest file
添加应用程序清单文件
import UIKit
import SwiftUI
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//guard let _ = (scene as? UIWindowScene) else { return }
let user = UserDefaults.standard.object(forKey: "defaultsuserid")
let userSelfIdent = UserDefaults.standard.object(forKey: "userinitialident")
if let windowScene = scene as? UIWindowScene {
let internalWindow = UIWindow(windowScene: windowScene)
if (user != nil && userSelfIdent != nil){
let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
internalWindow.rootViewController = newViewcontroller
self.window = internalWindow
internalWindow.makeKeyAndVisible()
}else {
guard let _ = (scene as? UIWindowScene) else { return }
}
}
}
The following is my AppDelegate which is getting called first and executing the didFinishLaunchWithOptions
method. I want to know how can i make this method call only if my Target ios is less than 13.0 and call SceneDelegate method to initialize my rootViewController after 13.0?
以下是我的 AppDelegate,它首先被调用并执行该didFinishLaunchWithOptions
方法。我想知道如何仅当我的 Target ios 小于 13.0 并在 13.0 之后调用 SceneDelegate 方法来初始化我的 rootViewController 时才能调用此方法?
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
@available(iOS 13.0, *)
func application(_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
@available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}
@available(iOS 13.0, *)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
if (user != nil && userSelfIdent != nil){
let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
self.window?.rootViewController = newViewcontroller
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
Thread.sleep(forTimeInterval: 3.0)
UINavigationBar.appearance().barTintColor = UIColor(red:0.08, green:0.23, blue:0.62, alpha:1.0)
if (user != nil && userSelfIdent != nil){
let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
self.window?.rootViewController = newViewcontroller
}
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let defaultUserID = UserDefaults.standard.string(forKey: "defaultUserID")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
switch (application.applicationState) {
case UIApplicationState.active:
do something
case UIApplicationState.background, UIApplicationState.inactive:
let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewcontroller = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
self.window?.rootViewController = newViewcontroller
}
}
回答by rmaddy
You have several issues here. It's important to read the documentation related to the app lifecycle which states what is called under iOS 13 and what is called under iOS 12.
你在这里有几个问题。阅读与应用程序生命周期相关的文档很重要,其中说明了在 iOS 13 下调用的内容和在 iOS 12 下调用的内容。
You may also want to see my Single View App templatethat supports iOS 12 and 13.
您可能还想查看我的支持 iOS 12 和 13 的Single View App 模板。
Looking at your code, here is a summary of the problems:
查看您的代码,这里是问题的摘要:
AppDelegate:
应用委托:
- You should only setup the main window and the root view controller if the app is being run under iOS 12 or earlier. You need to check this at runtime.
- The
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
method should not be in the app delegate. - Not directly related but never sleep on app startup. Remove the
Thread.sleep(forTimeInterval: 3.0)
line. Users want to use your app, not stare at the launch screen longer than necessary. And blocking the main thread on app launch can cause your app to be killed.
- 如果应用程序在 iOS 12 或更早版本下运行,您应该只设置主窗口和根视图控制器。您需要在运行时检查这一点。
- 该
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
方法不应在应用程序委托中。 - 没有直接关系,但在应用程序启动时从不休眠。删除
Thread.sleep(forTimeInterval: 3.0)
线。用户希望使用您的应用程序,而不是盯着启动屏幕的时间过长。在应用程序启动时阻塞主线程可能会导致您的应用程序被终止。
SceneDelegate:
场景委托:
- This is mostly fine but there is no reason for the
guard let _ = (scene as? UIWindowScene) else { return }
line, especially since it is inside anif let
that already does that check. - You don't appear to be using SwiftUI so remove that import.
- 这基本上没问题,但没有理由进行该
guard let _ = (scene as? UIWindowScene) else { return }
行,特别是因为它在if let
已经进行该检查的内部。 - 您似乎没有使用 SwiftUI,因此请删除该导入。
I would update your app delegate to be more like this:
我会将您的应用程序委托更新为更像这样:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
UINavigationBar.appearance().barTintColor = UIColor(red:0.08, green:0.23, blue:0.62, alpha:1.0)
if #available(iOS 13.0, *) {
// In iOS 13 setup is done in SceneDelegate
} else {
let window = UIWindow(frame: UIScreen.main.bounds)
self.window = window
if (user != nil && userSelfIdent != nil){
let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
window.rootViewController = newViewcontroller
}
}
return true
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
// In iOS 13 setup is done in SceneDelegate
} else {
self.window?.makeKeyAndVisible()
}
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Not called under iOS 13 - See SceneDelegate sceneWillResignActive
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Not called under iOS 13 - See SceneDelegate sceneDidEnterBackground
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Not called under iOS 13 - See SceneDelegate sceneWillEnterForeground
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Not called under iOS 13 - See SceneDelegate sceneDidBecomeActive
}
// 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.
}
}
Your scene delegate could be like:
你的场景委托可能是这样的:
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
self.window = window
if (user != nil && userSelfIdent != nil){
let mainstoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "swrevealviewcontroller") as! SWRevealViewController
window.rootViewController = newViewcontroller
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Not called under iOS 12 - See AppDelegate applicationDidBecomeActive
}
func sceneWillResignActive(_ scene: UIScene) {
// Not called under iOS 12 - See AppDelegate applicationWillResignActive
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Not called under iOS 12 - See AppDelegate applicationWillEnterForeground
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Not called under iOS 12 - See AppDelegate applicationDidEnterBackground
}
}
回答by Vinayak Bhor
So steps to getting to an iOS 13 and lower version
所以升级到 iOS 13 及更低版本的步骤
1) Change deployment target to iOS 12.
1) 将部署目标更改为 iOS 12。
2) Replace the AppDelegate's methods with what they ought to have for iOS 12 development. Also add this:
2) 将 AppDelegate 的方法替换为 iOS 12 开发应具备的方法。还要添加这个:
var window: UIWindow?
3) Remove SceneDelegate.
3) 删除SceneDelegate。
4) Remove Application Scene Manifest in your info.plist.
4) 在 info.plist 中删除 Application Scene Manifest。
It will work on both iOS 13 and lower iOS Version
它适用于 iOS 13 和更低的 iOS 版本
回答by Emre Gürses
Easly fallow these steps
轻松休养这些步骤
1-) Remove scene delegate file
1-) 删除场景委托文件
2-) Add below code to AppDelegate.swift
2-) 将以下代码添加到 AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
}
3-) Remove the Application Scene Manifest line from your .plist file
回答by Erick Martinez
I was stuck with this problem, and finally i solved removing the searchDisplayController references from storyboard.
我被这个问题困住了,最后我解决了从故事板中删除 searchDisplayController 引用的问题。
<searchDisplayController id="pWz-So-g6H">
<connections>
<outlet property="delegate" destination="Yci-sd-Mof" id="fjs-ah-jLs"/>
<outlet property="searchContentsController" destination="Yci-sd-Mof" id="gQN-1r-gti"/>
<outlet property="searchResultsDataSource" destination="Yci-sd-Mof" id="2Jf-lh-Ute"/>
<outlet property="searchResultsDelegate" destination="Yci-sd-Mof" id="Hap-SA-f02"/>
</connections>
</searchDisplayController>
回答by appleitung
When I had a similar issue it was due to the Single-App template generated using Xcode 11.0 was incompatible to the one being needed for an app built with Xcode 11.2.
当我遇到类似问题时,是因为使用 Xcode 11.0 生成的 Single-App 模板与使用 Xcode 11.2 构建的应用程序所需的模板不兼容。
So I just created a new Single-Page-App with Xcode 11.2 and copied the generated SceneDelegate to my old project which was created using Xcode 11.0.
所以我刚刚使用 Xcode 11.2 创建了一个新的单页应用程序,并将生成的 SceneDelegate 复制到我使用 Xcode 11.0 创建的旧项目中。
After that, the blank screen was gone an my interface visible once more.
之后,空白屏幕消失了,我的界面再次可见。