I have implemented two different UIViewControllers, that should replace each other based on server respond and user actions. For simplicity let's think that we have two UIViewControllers with button replace with another, that should trigger this replacement.
Now I need to do that replace part, but the problem is there is some delay between dismissing one screen and showing the other. I want to somehow get rid of it. I show UIViewController modally with present method.
I thought about making these two screen as views in xib-files, and one UIViewController that will be loading these xibs, adding them as subViews and replacing one subView with another when it needs it, but maybe there is a way to do that with two UIViewControllers?
Code that I use to present controller:
let vc = UIViewController1()
vc.modalPresentationStyle = .overFullScreen
self.present(vc, animated: false, completion: nil)
And to dismiss:
self.dismiss(animated: false, completion: nil)
you can add a container view and in that view you can simply add your desired controller as the child view controller
official doc reference.
another reference
Set the present method's "animate" parameter to be false
To Present
let vc = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
self.present(vc, animated: false, completion: nil)
To Dismiss
self.dismiss(animated: false, completion: nil)
First you send notification to parent class for present another 'viewController' and then dismiss current class
Note: Both present class method set animation false
Related
Hello I am pretty annoyed with this:
Originally, I had many segues in my storyboard. Each button at bottom of tool bar would segue to various view controllers. As you can imagine, that is a lot of segues for 6 different items on toolbar. After segueing, each action would call self.dismiss and everything would be ok.
Recently, I wanted to clean up the storyboard.
I created the function:
extension UIViewController {
func segue(StoryboardID: String) {
let popOverVC = UIStoryboard(name: "Main", bundle:
nil).instantiateViewController(identifier: StoryboardID)
popOverVC.modalPresentationStyle = UIModalPresentationStyle.fullScreen
popOverVC.modalTransitionStyle = .crossDissolve
self.dismiss(animated: false, completion: nil)
print("dismissed")
self.present(popOverVC, animated: false, completion: nil)
print("presented")
}
}
What I am seeing is that the dismiss dismisses the new view controller from appearing. It essentially goes back to my first view controller presented upon launch. I want to dismiss all view controllers so that I don't keep piling up my views.
Thanks
The problem is that you present your popOverVC from a view controller that is being dismissed, so your popOverVC will never be shown as its parent is being dismissed.
Not sure how your architecture is exactly but you would either need to use the delegate pattern to tell the parent when to segue, for example:
self.dismiss(animated: true) {
self.delegate?.didDismiss(viewController: self)
}
Or to use some trick to get the top most view controller to present your popOverVC after the current view has been dismissed, ex:
self.dismiss(animated: true) {
var topController: UIViewController = UIApplication.shared.windows.filter{$0.isKeyWindow}.first!.rootViewController!
while (topController.presentedViewController != nil) {
topController = topController.presentedViewController!
}
topController.present(popOverVC, animated: true)
}
But I agree with #Paulw11, a UITabBarController seem like a much better option for what you're trying to do.
From some ViewController of my UINavigationController stack I present another ViewController and will never come back, but the problem is that deinit{} is not called. How should I remove each ViewController from the stack before navigation? Or should I use some other method? Now my code looks like
let destinationVC = storyboard?.instantiateViewControllerWithIdentifier("revealViewController") as! SWRevealViewController
self.presentViewController(destinationVC, animated: true, completion: nil)
First of all, when you call presentViewController:animated:completion: you will present the new viewController modally, outside of the navigationController's hierarchy.
If you wish to present it within the navigationController hierarchy use:
self.navigationController!.pushViewController(destinationVC, animated: true)
And if you want to change the view hierarchy, the navigationController has a property viewControllers which can be set with or without animation.
self.navigationController!.setViewControllers([destinationVC],
animated: true)
See the iOS Developer Library for more information.
I want to use a third-party library which implements a nice tabbar controller. But it does all the work programmatically, basically all it does is create two uiviewcontrollers and add them to a tabbarcontroller, and then instantiate an uinavigationcontroller with the tabbarcontroller. In the last step, it assigns the uinavigationcontroller to the rootviewcontroller of the window like the following:
self.window?.rootViewController = getNavigationController()
But I want to use this navigationcontroller in a place other than the rootviewcontroller of the window, say like I want to push from another view and goes to this navigationcontroller. How can I achieve that?
You can present it modally over your current navigation controller from your current viewcontroller
let vc = myNavigationControllerWithTabBarControllerInside() //change this to your navigation controller
self.navigationController.presentViewController(vc, animated: true, completion: nil)
Please verify, for your self.navigationController to not be nil. otherwise, use
self.presentViewController(vc, animated: true, completion: nil)
I have a ViewController and another second controller called FlavorsController.
My ViewController is my initial view controller. It does not have a navigation controller. I go to the FlavorsController using the following command:
let controller = storyboard?.instantiateViewControllerWithIdentifier("FlavorsController") as! FlavorsController
presentViewController(controller, animated: true, completion: nil)
I have a NavigationController that is set on FlavorsController however it is not showing up.
You should present the Navigation Controller instead of the FlavorsController, so code should look like this:
let controller = storyboard?.instantiateViewControllerWithIdentifier("NavControllerID") as! NavBarControllerName
presentViewController(controller, animated: true, completion: nil)
See that NavControllerID and NavBarControllerName are just names invented by me. Just set the ones you have set in your storyboard.
i'm trying to pass Data to a viewController. The problem is that its embedded in a navigationController and is presented modally. How can i pass to a viewController which is presented modally and is embedded in a navigation Controller
func offerNew(sender: UIBarButtonItem) {
let offerVC = self.storyboard?.instantiateViewControllerWithIdentifier("OfferViewController") as UINavigationController
self.presentViewController(offerVC, animated: true, completion: nil);
}
i've tried this
let offerVC = self.storyboard?.instantiateViewControllerWithIdentifier("offerNavigation") as UINavigationController
let targetVC = offerVC.topViewController as OfferViewController
self.presentViewController(targetVC, animated: true, completion: nil);
I'm assuming that offerVC is the navigationController in which your "target" view controller is embedded. If so, your target view controller can be accessed through the topViewController property of offerVC. So
let targetVC = offerVC.topViewController as TargetViewController
will give you a reference. You can then access the properties of your target view controller.
EDIT
But you should present OfferVC - it will display targetVC automatically.
self.presentViewController(offerVC, animated: true, completion: nil);
You could add a property to your OfferViewController, then assign it. Your view initialization code would be done in loadView, which won't be called until after presentViewController, so not having it during init shouldn't be a problem in most cases.