Search code examples
iosswiftios13

iOS 13 iPhone 10 and 11 Only shows black view but expecting UITabBarController [View hierarchy shows it has NO height]


All version and phones are okay, running smoothly but in iPhone 11 Everything just turned black. I am not using storyboard, the UI are made in code and the pattern is MVVMC. Any idea why on in iPhone 11 the app turned black?

Images: https://i.sstatic.net/hnjdG.png

This is the view hierarchy: https://www.dropbox.com/s/e3mzzpwn8iozhc0/Screen%20Shot%202019-10-08%20at%2012.11.18%20PM.png?dl=0

[EDIT: PLEASE TAKE NOTE THAT THE APP WAS BUILT IN XCODE 10.2.1]

The rootViewcontroller is TabBarController.

in AppDelegate.swift

var window: UIWindow?
private var appCoordinator: AppCoordinator!

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    FirebaseApp.configure()

    window = UIWindow()
    appCoordinator = AppCoordinator(window: window!)
    appCoordinator.start{}

    return true
}

func applicationWillTerminate(_ application: UIApplication) {
    //TODO: avoid relogout

}

in TabCoordinator.swift

enum SectionTab: Int, Menu {
    //case home
    case futures
    case trading
    case wallet
    case account

    func title(languageManager: LanguageManager) -> String {
        switch self {
        //case .home: return languageManager.localizedString("router.home")
        case .futures: return languageManager.localizedString("router.futures")
        case .trading: return languageManager.localizedString("router.spot")
        case .wallet: return languageManager.localizedString("router.wallets")
        case .account: return languageManager.localizedString("router.account")
        }
    }

    var image: UIImage {
        switch self {
        //case .home: return UIImage.init(named: "icTabHome")!
        case .futures: return UIImage.init(named: "icTabFutures")!
        case .trading: return UIImage.init(named: "icTabTrading")!
        case .wallet: return UIImage.init(named: "icTabWallet")!
        case .account: return UIImage.init(named: "icTabAccount")!
        }
    }

    var highlightedImage: UIImage {
        switch self {
        //case .home: return UIImage.init(named: "icTabHomeActive")!
        case .futures: return UIImage.init(named: "icTabFutures")!
        case .trading: return UIImage.init(named: "icTabTradingActive")!
        case .wallet: return UIImage.init(named: "icTabWalletActive")!
        case .account: return UIImage.init(named: "icTabAccountActive")!
        }
    }

}

init(window: UIWindow, dependencies: Dependencies) {
    self.window = window
    self.dependencies = dependencies
}

override func start(completion: @escaping CoordinatorCompletion) {
    super.start(completion: completion)

    let tabbarController = UITabBarController()
    let tabs : [SectionTab] = [.futures, .trading, .wallet, .account]
    let viewControllers = createViewControllers(tabs: tabs)

    tabbarController.viewControllers = viewControllers.map{ $0.viewController }
    tabbarController.view.backgroundColor = .white
    tabbarController.tabBar.tintColor = UIColor.appLightBlue
    tabbarController.tabBar.unselectedItemTintColor = UIColor.appDarkGray

    let notification = Notification.Name.init(LanguageChangedNotification)
    NotificationCenter.default.rx.notification(notification).subscribe({_ in
        tabbarController.viewControllers?.enumerated().forEach({ (arg0) in
            let (offset, vc) = arg0
            vc.tabBarItem.title = tabs[offset].title(languageManager: self.dependencies.languageManager)
        })
    }).disposed(by: disposeBag)

    window.rootViewController = tabbarController
    window.makeKeyAndVisible()
}

private func createViewControllers(tabs: [SectionTab]) -> [(viewController: UIViewController, coordinator: BaseCoordinator)] {
    return tabs.map({ (tab) -> (viewController: UIViewController, coordinator: BaseCoordinator) in
        let viewController: UIViewController

        let coordinator: BaseCoordinator
        switch tab {
        case .futures:
            viewController = BTSENavigationController()
            coordinator = FuturesCoordinator(navigationController: viewController as! BTSENavigationController, dependencies: dependencies)
            coordinate(to: coordinator)
        case .trading:
            viewController = BTSENavigationController()
            coordinator = SpotCoordinator(navigationController: viewController as! BTSENavigationController, dependencies: dependencies)
            coordinate(to: coordinator)
        case .wallet:
            viewController = BTSENavigationController()
            coordinator = WalletCoordinator(navigationController: viewController as! BTSENavigationController, dependencies: dependencies, url: self.dependencies.client.url(for: .wallets))
            coordinate(to: coordinator)
        case .account:
            viewController = BTSENavigationController()
            coordinator = AccountCoordinator(navigationController: viewController as! BTSENavigationController, dependencies: dependencies)
            coordinate(to: coordinator)
        }

        viewController.tabBarItem = UITabBarItem.init(title: tab.title(languageManager: dependencies.languageManager), image: tab.image, selectedImage: tab.highlightedImage)

        return (viewController: viewController, coordinator: coordinator)
    })
}

Solution

  • even if i just do this on the AppDelegate:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
            FirebaseApp.configure()
    
            window = UIWindow()
            window.rootViewController = UIViewController() //this should show white screen
    
            return true
    }
    

    The app will show black screen since the rootviewController has no delegate. Seems like I really have to implement the Scenedelegate.