Black screen when changing root view controller in AppDelegate - ios

I am trying to change the root view controller from the app delegate's didFinishLaunchingWithOptions, depending on whether the user is logged in or not. Once I get past this condition, I am using the following code to change root view controllers:
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SWRevealViewController") as! SWRevealViewController
self.window?.makeKeyAndVisible()
However, when I launch the app (with a valid logged in user) the simulator first shows the log in screen (old root view controller) for a second, then the screen goes black for about 30 seconds to a minute, before finally showing the desired view controller.
The view controller structure in storyboard is as follows:
SWRevealViewController -> Navigation Controller -> Desired View Controller (new root)
The reason for beginning with SWRevealViewController is because the slide menu is lost otherwise.
Any ideas of what might be going on?

I found a way to produce a similar result to the one I desired. It involves not changing the root view controller at all, and having it present an "artificial root view controller" after launch:
if let currentRoot = self.window?.rootViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let artificialRoot = storyboard.instantiateViewController(withIdentifier: "SWRevealViewController")
currentRoot.present(artificialRoot, animated: false, completion: nil)
}
Although not ideal, the results of this implementation are by far better than the implementation in the question description.

Here is an example, that works for me, just make your loginViewControllers to be a stack of UINavigationController, not related to SWRevealController. It is easy workaround.
self.window = UIWindow(frame: UIScreen.main.bounds)
if User.shared.firstLaunch {
let navigationVC = Storyboard.inital.instantiateViewController(withIdentifier: "firstLaunchNC") as! UINavigationController
self.window?.rootViewController = navigationVC
} else if User.shared.token == "" {
let navigationVC = Storyboard.inital.instantiateViewController(withIdentifier: "initialVC") as! UINavigationController
self.window?.rootViewController = navigationVC
} else {
self.registerForPushNotifications(application: UIApplication.shared)
User.shared.refreshToken()
let revealController = Storyboard.main.instantiateViewController(withIdentifier: "revealViewController") as! SWRevealViewController
self.window?.rootViewController = revealController
}
self.window?.makeKeyAndVisible()
return true

try this:
let viewController = ViewController()
let navigationController = UINavigationController(rootViewController: viewController)
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()

try this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UITabBarController *tbc = [storyboard instantiateViewControllerWithIdentifier:#"TabBarController"];
tbc.selectedIndex=[singleton getSelectedTabIndex];
// tbc.selectedIndex=0;
//self.window.rootViewController = tbc;
[self.window setRootViewController:tbc];
[UIView transitionWithView:self.window duration:0.3 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil
completion:nil];
If This not work..Please check your initial Controller ...In Which Never try Load NSAtrributedString
NSAttributedString *attrStr = [[NSAttributedString alloc]
initWithData:[htmlString dataUsingEncoding:NSUnicodeStringEncoding]
options:#{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: #(NSUTF8StringEncoding)}
documentAttributes:nil
error:nil];
Note:-- Black Screen Apear When Initial Controller ViewDidLoad Take Some time to load UIview into Memory due some Lazy UI loading Assests are done in ViewDidLoad...
Try heavy load view cide into ViewWillApear or ViewDidApear ....

Related

iOS Swift: Pushing two view controllers when app launched from push notification

When a user launches the app from a push notification I present one view controller, then push another. My code to present the first VC is as follows
let mainStoryBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let homeNav: UIViewController = mainStoryBoard.instantiateViewController(withIdentifier: "HomeNavController") as! UINavigationController
let homePageTableVC = mainStoryBoard.instantiateViewController(withIdentifier: String(describing: HomePageTableViewController.self)) as! HomePageTableViewController
homePageTableVC.tipToPresent = tipDay
homeNav.addChildViewController(homePageTableVC)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = homeNav
self.window?.makeKeyAndVisible()
The tipToPresent property is used by the homePageTableVC (in the viewDidLoad method) to then present the second VC, using this code:
if let tipDayToPresent = tipToPresent {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tipVC = storyboard.instantiateViewController(withIdentifier: String(describing: TipViewController.self)) as! TipViewController
tipVC.dayOfTip = tipDayToPresent
tipToPresent = nil
navigationController?.pushViewController(tipVC, animated: true)
}
This works well, but when I press the back button to return to the homePageTableVC, the navigation bar is blank. The title image, menu button, and right bar button that normally show up are not visible.
Any help is appreciated.
Good if solution by #augie works. I would suggest you should not change navigation stack when you handle push notification deep link. It should behave same as it does in normal app launch. By that way you don't need to handle any edge case and no need to set up different window.
Solution: Whenever someone click on push notification dismiss all presented controller and popToRootViewController and then navigate to desired screen.
Can you try changing this
homeNav.addChildViewController(homePageTableVC)
to this
homeNav.setViewControllers([homePageTableVC], animated: false)
I believe the problem is how you are adding your table on the navigation controller. Instead of making it your navigation's root viewcontroller you are adding it as a child vc.
Changing your code like this should work:
let mainStoryBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
// Remove type UIViewController
let homeNav = mainStoryBoard.instantiateViewController(withIdentifier: "HomeNavController") as! UINavigationController
let homePageTableVC = mainStoryBoard.instantiateViewController(withIdentifier: String(describing: HomePageTableViewController.self)) as! HomePageTableViewController
homePageTableVC.tipToPresent = tipDay
// Set controllers instead of adding child
homeNav.setViewControllers([homePageTableVC], animated: false)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = homeNav
self.window?.makeKeyAndVisible()

Getting warning "Presenting view controllers on detached view controllers is discouraged" while making window root view controller in app delegate?

Here is the code
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "homeTBC") as! UITabBarController
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
cant figure it yet.
I have tried this code in My App for root view controller in app delegate working perfect:
As I think you are using this code in presented view controller or in presented navigation controller: Please send the scenario(Screen Shot) exact what you are doing?
var window: UIWindow?
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "TabbarVC") as! TabbarVC
self.window?.rootViewController = vc
From Apple's Documentation
When creating windows, always set the window’s initial size and
specify the screen on which it is displayed.
Add the size:
self.window = UIWindow.init(frame: UIScreen.main.bounds)
Your complete code should be like that:
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "homeTBC") as! UITabBarController
self.window = UIWindow.init(frame: UIScreen.main.bounds)
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()

How to reset root view controller

Is it possible to reset the root view controller? With reset I mean resetting it to its initial state so viewDidLoad will be called again. I'm using a UITabBarController and when I logout I want all the tabs previously loaded to be unloaded.
You can do this by setting the instance of TabBarController to rootViewController on logout action.
Swift 3:
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyBoard.instantiateViewController(withIdentifier: "TabBarController") as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = tabBarController
UIApplication.shared.keyWindow?.makeKeyAndVisible()
Objective C:
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UITabBarController *tabBarController = [storyBoard instantiateViewControllerWithIdentifier:#"TabBarController"];
[[[UIApplication sharedApplication] keyWindow] setRootViewController:tabBarController];
[[[UIApplication sharedApplication] keyWindow] makeKeyAndVisible];
If you are using navigation controller on Tabbarcontroller then navigate to that navigation controller otherwise go to Tabbarcontroller as-
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabBar = mainStoryboard.instantiateViewControllerWithIdentifier("TabBarController") as! TabBarController
appDelegate.window?.rootViewController = tabBar
appDelegate.window?.makeKeyAndVisible()
Set view property of UIViewController to nil
UIApplication.shared.keyWindow?.rootViewController?.view = nil
it will force UIViewController to init his life cycle from a beginning after next call to self.view

Swift showing view only on first launch with navigation controller

I have some code to only show the first view controller in my storyboard on the first launch of the app. After that I want to skip that page and go straight to my second view on each launch. I have embedded the first view (which is connected to the second) in a navigation controller.
My issue is that after the first launch when the app goes to the second view directly it's showing the view without the navigation bar on top and I'm not sure why.
In my appdelegate:
func firstLaunchCheck(){
let launchedBefore = UserDefaults.standard.bool(forKey: "launchedBefore")
if launchedBefore{
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialView : UIViewController = storyboard.instantiateViewController(withIdentifier: "mainScreen") as UIViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialView
self.window?.makeKeyAndVisible()
}
else{
UserDefaults.standard.set(true, forKey: "launchedBefore")
}
}
UPDATE:
I wound up just changing which view controller were embedded in the navigation controller (excluded the first one) since it didn't make sense to me to have it there. So now after the first launch it loads the navigation controller
SecondViewController is not added in UINavigationController hierarchy, to see the navigationBar on top you can push SecondViewController on firstVC if the launchedBefore is false in appDelegate
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondVC = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
let navigationController = window.rootViewController as! UINavigationController
navigationController?.pushViewController(secondVC, animated: false)
You need to embed the second view controller i.e. "mainScreen" in UINavigationController and then make it the rootViewController of your app window.
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = UINavigationController.init(rootViewController: storyboard.instantiateViewController(withIdentifier: "mainScreen"))
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialView
self.window?.makeKeyAndVisible()

programmatically set initial view controller to tab controller swift 2

I have a tab controller on my iOS App and I want to check some conditions first and do as follow:
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if condition {
globalClass.token = u
let mvc: MainViewController = mainStoryBoard.instantiateViewControllerWithIdentifier("mainView") as! MainViewController
self.window?.rootViewController = mvc
} else {
globalClass.token = ""
let mvc: LoginViewController = mainStoryBoard.instantiateViewControllerWithIdentifier("loginView") as! LoginViewController
self.window?.rootViewController = mvc
}
self.window?.makeKeyAndVisible()
My problem is that when I programmatically set the initial view controller to first tab of the tab controller when it is loaded, the tab menus at bottom won't load. It just loads the view controller not tab menu.
MainViewController is the first tab of the tab view controller
Thanks,
Afshin
Try this code.
let tbc = mainStoryBoard.instantiateViewControllerWithIdentifier("tabbarStoryboardId") as! UItabBarController
self.window?.rootViewController = tbc
Thanks

Resources