App crash on pushViewController after popToViewController - ios

I have tried to search for this, but can't find any perfect solution.
My app has custom animating views and both side drawers.I also have custom navigationController which has sliding top bar.From appDelegate I'm setting first controller as rootViewController and then pushing ViewController(i.e. mainViewController with animations).
then trying to push second controller. From second controller I can go to either third controller or rootViewController on button Click.
And app crashes when I tried to go to second viewController after getting back from secondController using popToViewController.
I'm setting rootViewController at appdelegate as:
let profileViewController = mainStoryboard.instantiateViewController(withIdentifier: "LoadingDataView") as! LoadingDataView
self.navigationController = SDNavigationController(rootViewController: profileViewController);
self.navigationController.navigationBar.isHidden=true;
self.window!.rootViewController = self.navigationController
self.window!.makeKeyAndVisible()
Pushing ViewController(mainController) as:
if( app.navigationController.viewControllers.count < 2){
let profileViewController=mainStoryboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
app.navigationController?.pushViewController(profileViewController, animated: true);
}else{
let profileViewController=mainStoryboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
app.navigationController?.pushViewController(profileViewController, animated: false);
let emptyView = UIViewController();
app.navigationController?.pushViewController(emptyView, animated: false);
app.navigationController.popViewController(animated: true);
}
Then pushing second viewController as:
let tutorialView=myStory.instantiateViewController(withIdentifier: "BookmarksDetails") as! BookmarksDetails;
self.navigationController!.pushViewController(tutorialView, animated: true);
getting back from second viewController as:
let testController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController") as! ViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
testController.isOpenLeftDrawer = true
appDelegate.window?.rootViewController = testController
self.navigationController?.popToRootViewController(animated: true)
app crashes when I tried to go to secondViewController from viewController(mainController).

Why you are doing this -
app.navigationController.popViewController(animated: true);
Just only push and don't use the pop ViewController code here.

Related

ios swift cannot dismiss view controller

I am opening new viewcontroller like
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let view_controller1 = storyBoard.instantiateViewController(withIdentifier: "incident_view_id") as! IncidentViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
//self.present(registerViewController, animated: true)
let navigationController = UINavigationController.init(rootViewController: view_controller1)
appDelegate.window?.rootViewController = navigationController
Which works fine,
Now when I press a button I need to close current view and go back previous view, I tired
self.navigationController?.popToRootViewController(animated: true)
But not works, I tried this too
self.view.window!.rootViewController?.dismiss(animated: true, completion: nil)
But same result.
You are presenting your ViewController in a wrong way. The following line tells the application to no matter what ViewControllers you have opened, just throw it out and assign the UINavigationController what you are creating, as the rootViewController. So the reason your code, the dismiss, is not working because there are no other ViewControllers behind your current one.
appDelegate.window?.rootViewController = navigationController // Wrong
This usually goes into the beginning of the applications, where you define with which UIViewController you want to start your application. I believe you are calling the first code chunk you posted from a UIViewController. So what you need to do instead of creating a new UINavigationController and assigning it to the rootViewController, you just use the UIViewControllers navigation controller to push the next UIViewController.
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let view_controller1 = storyBoard.instantiateViewController(withIdentifier: "incident_view_id") as! IncidentViewController
navigationController?.pushViewController(view_controller1, animated: true)

When should I set rootViewController? it's very confused

Hi I am struggling with rootViewController I left some code fragment with an explanation below, please let me know.
If I do it like below, it works and every things fine.
private func presentLogin() {
log.info("presenting login..")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let vc = storyboard.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
vc.modalPresentationStyle = .fullScreen
appDelegate.window!.rootViewController = vc
present(vc, animated: false)
}
right after that if I execute the code below, ios shows nothing but white blank page..
private func presentMain() {
log.info("presenting main..")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let vc = storyboard.instantiateViewController(withIdentifier: "MainTabBarController") as! MainTabBarController
vc.modalPresentationStyle = .fullScreen
appDelegate.window!.rootViewController = vc
present(vc, animated: false)
}
but when I deleted the code
appDelegate.window!.rootViewController = vc
everything is fine.
In other words, the code below works only the first time.
appDelegate.window!.rootViewController = vc
why? what am I missing?, I don't understand..
It seems there are a lot of bugs concerning the exchange of the root view controller. Switching the root view controller is also a little uncommon way of "navigation". I would recommend a different approach:
Upon app startup, use a "launch" view controller. This is your root view controllers, and it stays to be your root view controller all the time
if login is required, present a login view controller
after successful login, dismiss the login view and go on
if logged in, present the main application's entry view

How to invoke Navigation controller form a VC

I have 3 VC's (VC as in ViewController)
1 AuthViewController which is the entry point for the app and it checks if user is logged in else it displays the sign-in related views
2 HomeViewController is the main interface of the app landing page after the user has logged in
3 ListViewController which displays a list, invoked via a segue on HomeViewController.
I want to enable back navigation between ListViewController and HomeViewController via a Navigation Controller.
How can I achieve this If I have a Navigation controller whose root VC is HomeVC. how can I invoke it from my AuthVC so that it gets invoked with the Navigation controller.
I have tried to invoke the Navigation controller but did not work
I have also tried invoking the HomeVC by
let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
if let viewController = mainStoryboard.instantiateViewController(withIdentifier: "mainViewController") as? UIViewController {
viewController.modalPresentationStyle = .overCurrentContext
self.present(viewController, animated: true, completion: nil)
although I was able to invoke the HomeVC could not get the navigation buttons
How can I invoke HomeVC from the AuthVC without loosing the NavigationController
You need 1 navigation controller, not 3.
If you want to push a new controller, then use push method, not present.
The back button gets enabled automatically on the navigation bar if there are controllers in the navigation stack and the current controller is not a root view controller.
When coming from AuthViewController to HomeController, you should change the RootViewController. So that the user cant go back to the Auth screen. That would make no sense.
Once you are on HomeController, you can push other controller using the below code and it will add a back button to your controller automatically.
let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
if let viewController = mainStoryboard.instantiateViewController(withIdentifier: "mainViewController") as? UIViewController {
self.navigationController?.pushViewController(vc, animated: true)
}
You can also use the below extension:
extension UIViewController {
func pushVC(storyboardName : String, vcname : String) {
let vc = UIStoryboard.init(name: storyboardName, bundle: Bundle.main).instantiateViewController(withIdentifier: vcname)
vc.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(vc, animated: true)
}
func popVC() {
self.navigationController?.popViewController(animated: true)
}
func makeRootVC(storyBoardName : String, vcName : String) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let vc = UIStoryboard(name: storyBoardName, bundle: Bundle.main).instantiateViewController(withIdentifier: vcName)
let nav = UINavigationController(rootViewController: vc)
nav.navigationBar.isHidden = true
appDelegate.window?.rootViewController = nav // If using XCode 11 and above, copy var window : UIWindow? in your appDelegate file
let options: UIView.AnimationOptions = .transitionCrossDissolve
let duration: TimeInterval = 0.6
UIView.transition(with: appDelegate.window!, duration: duration, options: options, animations: {}, completion: nil)
}
}

Load all views related to tab bar controller by hard code

I would like to jump from a viewController to the first viewController related to Tab Bar Controller through code.
The tabBarController Scene has storyboard id tabView.
I'm working on this way:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc: UITabBarController!
storyboard.instantiateViewController(withIdentifier: "tabView")
vc=storyboard.instantiateViewController(withIdentifier: "tabView") as! UITabBarController
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.present(vc as! UIViewController, animated: true, completion: nil)
}
But it loads only the first viewController (out of 5) without the tab bar related to. How can I solve it?
Oh, this code looks so wrong.
In your storyboard give and "tabView" ID to the TabBarController, not the ViewController inside it.
Why you are double instantiating ViewController? just do it once and assign it to the vc variable.
Why you've created delay before presenting the VC? It's some sort of workaround of something?
Working code:
let vc = storyboard.instantiateViewController(withIdentifier: "tabView") as! UITabBarController
self.present(vc, animated: true)
Use
(1)if you want to navigate from Appdelegate
let appDelegate = UIApplication.sharedApplication.delegate as! AppDelegate
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabBar = mainStoryboard.instantiateViewControllerWithIdentifier("TabBarController") as! TabBarController
appDelegate.window?.rootViewController = tabBar
appDelegate.window?.makeKeyAndVisible()
(2)if you want to navigate from viewcontroller which has root of navigation
self.navigationController?.pushViewController(tabBar, animated: true)

Segue Presently from Appdelegate to UITabBarController in swift

I want to segue from AppDelegate to First View of UITabBarController.
I assigned StoryBoardID of UITabBarController as "HomePage".
and I tried below code:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController: UITabBarController = storyboard.instantiateViewControllerWithIdentifier("HomePage") as! UITabBarController
let rootViewController = self.window!.rootViewController as! UINavigationController
rootViewController.pushViewController(viewController, animated: true)
It works but I gave BackBarButton on destination view which I don't want.
I want to segue Presently.
You need to set your viewControllers instead of pushViewController
rootViewController.viewControllers = [viewController]
Instead of
rootViewController.pushViewController(viewController, animated: true)

Resources