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.
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.
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
I want to navigate between view controllers as it is shown. I do not want to use segues.
When I try to navigate form FirstViewController to SecondViewController by clicking a button:
let next = self.storyboard?.instantiateViewControllerWithIdentifier("secondViewController") as! SecondViewController
self.presentViewController(next, animated: true, completion: nil)
I get:
Warning: Attempt to present SecondViewController on FirstViewController whose view is not in the window hierarchy!
Any ideas how to insert Navigation Controllers in-between?
Edit: It is TabBarController not TabViewController on the figure.
I navigate from First Scene's controller named "A-Controller" to First View Controller with :
#IBAction func navigateToFirstViewController(sender: AnyObject) {
let next = self.storyboard?.instantiateViewControllerWithIdentifier("firstViewController") as! FirstViewController
self.presentViewController(next, animated: true, completion: nil)
}
It is not shown on the figure.
If you try to present modal view over TabBarController, then :
let next = self.storyboard?.instantiateViewControllerWithIdentifier("secondViewController") as! UIViewController
self.tabBarController.presentViewController(next, animated: true, completion: nil)
Warning: Attempt to present SecondViewController on FirstViewController whose view is not in the window hierarchy!
Turns out this error meant I have to do the navigation from First View to Second View after my First View appears and is ready.
Putting the navigation lines inside viewDidAppear() function solved the issue.
I have two views like this in Story Board:
[View1] -> [Navigation Controller] -> [View2]
To go from View1(has tableview) to View 2, i do this on click of a row on View1:
self.performSegueWithIdentifier("showmyview2", sender:self)
This works.
Now i have a button on View 2, which when clicked should take me back to previous view i.e View 1.
I tried this:
navigationController!.popViewControllerAnimated(true)
But this does not work. How do i go back to first view?
First Add a navigation controller to your First view1 through storyboard.(Editor->Embed Navigation controller), If navigation is not present.
OR
self.dismissViewControllerAnimated(true, completion: nil);
Call this function and try instead of navigation popviewcontroller
Use this code to present first view in your button action:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("FirstView") as! TableViewController
self.presentViewController(vc, animated: true, completion: nil)
And don't forget to give Id to your First view.
Select your firstView into storyBoard and then click on Identity Inspector and you can assign StoryBoard ID like show into below Image.
self.dismiss(animated: true, completion: nil);
this will work in swift 3
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.