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.
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.
Let say I have the following VCs:
RootVC --> VC A --> VC B
I'm using present method to present view controller from RootVC to VC A then to VC B. Now I'm on VC B and I want to dismiss from VC B back to RootVC using
self.view.window!.rootViewController?.dismiss(animated: true, completion: nil)
it works but I still see VC A shows up during the dismiss process. Then, I try this method
self.presentationController?.presentedViewController.dismiss(animated: true, completion: nil)
It also works to dismiss back to root VC but I still see VC A in process.
My question is is there a way to not show VC A during the dismiss process? I already try animated: false but still get the same result. Thanks!
You need to make the change in the modalPresentationStyle to the .custom. The custom will allow you to view the presentingViewController view when the current visible controller's view is transparent.
Now when you want to go back to root view on the current presenting stack you need to call the method dismissToRootViewController(animated: completion:).
In the implementation of this method will allow all intermediate presenting view controller view to be transparent which will give you dismiss animation from VC c to RootVC.
extension UIViewController {
func dismissToRootViewController(animated: Bool, completion: (() -> Swift.Void)? = nil) {
var viewController = self.presentingViewController
while viewController?.presentingViewController != nil {
viewController?.view.alpha = 0.0
viewController = viewController?.presentingViewController
}
self.dismiss(animated: true) {
viewController?.dismiss(animated: false, completion: completion)
}
}
}
You can try to use this:
navigationController?.popToRootViewController(animated: 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 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.