Swift 5 y Xcode 11
Entonces, en xCode 11, la solución de ventana ya no es válida dentro de appDelegate. Lo trasladaron al SceneDelgate. Puede encontrar esto en el archivo SceneDelgate.swift.
Notarás que ahora tiene un var window: UIWindow?regalo.
En mi situación, estaba usando un TabBarController de un guión gráfico y quería establecerlo como rootViewController.
Este es mi código:
sceneDelegate.swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
self.window = self.window ?? UIWindow()//@JA- If this scene's self.window is nil then set a new UIWindow object to it.
//@Grab the storyboard and ensure that the tab bar controller is reinstantiated with the details below.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "tabBarController") as! UITabBarController
for child in tabBarController.viewControllers ?? [] {
if let top = child as? StateControllerProtocol {
print("State Controller Passed To:")
print(child.title!)
top.setState(state: stateController)
}
}
self.window!.rootViewController = tabBarController //Set the rootViewController to our modified version with the StateController instances
self.window!.makeKeyAndVisible()
print("Finished scene setting code")
guard let _ = (scene as? UIWindowScene) else { return }
}
Asegúrese de agregar esto al método de escena correcto como lo hice aquí. Tenga en cuenta que deberá establecer el nombre del identificador para el tabBarController o viewController que está utilizando en el guión gráfico.

En mi caso, estaba haciendo esto para establecer un stateController para realizar un seguimiento de las variables compartidas entre las vistas de pestaña. Si desea hacer lo mismo, agregue el siguiente código ...
StateController.swift
import Foundation
struct tdfvars{
var rbe:Double = 1.4
var t1half:Double = 1.5
var alphaBetaLate:Double = 3.0
var alphaBetaAcute:Double = 10.0
var totalDose:Double = 6000.00
var dosePerFraction:Double = 200.0
var numOfFractions:Double = 30
var totalTime:Double = 168
var ldrDose:Double = 8500.0
}
//@JA - Protocol that view controllers should have that defines that it should have a function to setState
protocol StateControllerProtocol {
func setState(state: StateController)
}
class StateController {
var tdfvariables:tdfvars = tdfvars()
}
Nota: Simplemente use sus propias variables o lo que sea que esté tratando de hacer un seguimiento, en cambio, enumeré las mías como un ejemplo en tdfvariables struct.
En cada vista de TabController, agregue la siguiente variable miembro.
class SettingsViewController: UIViewController {
var stateController: StateController?
.... }
Luego, en esos mismos archivos, agregue lo siguiente:
extension SettingsViewController: StateControllerProtocol {
func setState(state: StateController) {
self.stateController = state
}
}
Lo que hace es permitirle evitar el enfoque singleton para pasar variables entre las vistas. Esto permite fácilmente el modelo de inyección de dependencia, que es mucho mejor a largo plazo que el enfoque singleton.