I have two TabBarController views embedded in a NavigationController and one View presented modally with its own NavigationController:
FeedView (1) (TableViewController -> Contained within TabBarController)
VenueView (2) (CollectionViewController -> Contained within TabBarController)
SelectView (3) (ViewController -> Modally presented from VenueView)
In VenueView (2), I have the following code to bring up SelectView (3):
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let selectNavigationController = self.storyboard?.instantiateViewControllerWithIdentifier("selectNavController") as! UINavigationController
let selectVC = selectNavigationController.topViewController as! SelectViewController
selectVC.currentVenue = venueItems[indexPath.row]
presentViewController(selectNavigationController, animated: true, completion: nil)
}
This allows me to bring up SelectView(3) without the tabbarcontroller, but still have a navbar. I have a button in SelectView(3) which I would like to use to persist an object's data and segue into FeedView(1).
I've tried many methods but the closest I've got to success was to segue to FeedView(1) but add more viewControllers (evidenced by buttons in navbar) and not have it contained within the TabBarController.
What is the correct way of creating this segue? I know how to persist the data but my question is more related to the proper technique of segueing from a modal View to the first tab of a BarTab.
Pic below for reference:
You could use an unwind segue if you stayed within the same navigation stack.
However, FeedView is on a different navigation controller.
One way to do it is to have your TabbarController switch back to FeedbackView (1st tab) using:
tabBarController.selectedIndex = 0
Related
I currently have parental "menu" TableView with UINavigationBar and from each cell there is a segues by reference outlet to 3 similar Views with different information.
In each View there is a buttons to other 2 Views.
With every button's segue opens another View.
The problem:
From every View UINavigationBar's back button returns me to previous View but i tries to make back button to "menu".
Additional Bar Button Item and segue from it makes very close effect but segue animation is not like in UINavigationController.
How I could clean UINavigationBar transitions history in segue to initial View?
You can try pop to root view controller or You can edit navigation controller viewControllers property and remove/add some VC in between.
You can try Unwind Segue mechanism too.
Here are some methods(function) that navigation controller providing for pop operations. They are returning optional UIViewController (intance) from it’s navigation stack, that is popped.
open func popViewController(animated: Bool) -> UIViewController? // Returns the popped controller.
open func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? // Pops view controllers until the one specified is on top. Returns the popped controllers.
open func popToRootViewController(animated: Bool) -> [UIViewController]?
Here is sample code as a solution to your query::
// if you want to back to root of your app
if let rootNavigationController = self.window?.rootViewController as? UINavigationController {
rootNavigationController.popToRootViewControllerAnimated(true)
}
// But if you want to back to root of your current navigation
if let viewcontroller = self.storyboard?.instantiateViewController(withIdentifier: "NewViewController") as? NewViewController { // or instantiate view controller using any other method
viewcontroller.navigationController?.popToRootViewControllerAnimated(true)
}
Hi people and please help
Am not using interface builder.
In AppDelegate:
...
tabBarController.viewControllers = [tabOne, tabTwo, tabThree, tabFour]
window?.rootViewController = UINavigationController(rootViewController: tabBarController)
...
in tabOne witch is UIViewController, lazy load UITableView with custom cell and in that cell row I lazy load UICollectionView.
And i need to push in navigationController some viewController?
Thanks
Please make tabBarController as rootViewController of window
Then create 4 navigationControllers for 4 viewController (tabOne, tabTwo, tabThree, tabFour) of tabbarController.
Like these codes:
let viewControllers = [UINavigationController(rootViewController: tabOne),
UINavigationController(rootViewController: tabTwo),
UINavigationController(rootViewController: tabThree),
UINavigationController(rootViewController: tabFour)]
tabBarController.viewControllers = viewControllers
window?.rootViewController = tabBarController
TabbarController is a containerViewController, so:
you need to create 4 navigationController for 4 tabs, because they have the particular flows.
as your code, tabOne.navigationViewController is nil so you can't push other viewcontroller because your navigationController doesn't belong to tabOne, it belongs to tabBarController.
You have to take callback from Collection view cell to the controller or class(which contains the UICollectionView, I think in your case table view cell's .m file)
Then callback on the controller which contains the main table view.
Now you are on the root view controller of the tab.
Push the navigation controller from here (If you already have any navigation controller)
Your case:
TabBarViewController -> RootViewController(One out of four tab) ->
TableView -> TableViewCell -> UICollectionView -> UICollectionViewCell
Take the callback on RootViewController Then you can do anything.
Remember You should have navigation controller to push another controller.
I find solution.
In super class for ViewControllers, create function that push to navigation, and from View (Cell) need to delegate self, and call that function. Thanks to all who try to help
I am developing an iOS app in Swift 2.3, XCode 8.0. My app has 4 tabs and to each of the tabs - 4 different View Controllers are connected. Inside the 4 View Controllers I have embedded Navigation controllers.
My requirement is that when a user selects tab 1 -> goes to ViewController 1 -> Next the user can go to 2nd View Controller as there is a navigation controller.
But when the user selects the second tab and then comes back to the first tab, instead of showing the first View Controller that is directly attached to tab 1, the View Controller that was last opened with the back button is shown.
How can I move directly move to the View Controller attached to the first tab?
The embedded navigation controller should automatically keep track of the stack for you regardless of which tab the user is in with the tab bar controller. Make sure each tab has its own navigation controller embedded into it instead of having the entire tab bar controller embedded in one navigation controller.
For example, if you implemented this programmatically:
let viewController1 = UIViewController()
let navigationController1 = UINavigationController()
navigationController1.setViewControllers([viewController1], animated: true)
let viewController2 = UIViewController()
let tabBarController1 = UITabBarController()
tabBarController1.setViewControllers([navigationController1, viewController2], animated: true)
Here the navigationController1 will keep track of which viewController is on top of the stack regardless of where the user is in the tab bar controller.
Thanks, I found the solution -
This works for me -
In my main tab bar viewController, I made it a delegate of both UITabBarController, UITabBarControllerDelegate and then implemented the didSelectViewController method of UITabBarControllerDelegate as below -
func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
let index : Int = (tabBarController.viewControllers?.indexOf(viewController))!
let navigationController = viewController as? UINavigationController
navigationController?.popToRootViewControllerAnimated(false)
}
I am looking for the best-practice method of doing the following:
I have two TabBarController views embedded in a NavigationController and one which I don't want to include as a tab but is embedded in a NavigationController:
FeedView (TableViewController)
VenueView (CollectionViewController)
SelectView (ViewController)
In VenueView (2), I have the following code to bring up SelectView (3):
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let selectVC: SelectViewController! = self.storyboard?.instantiateViewControllerWithIdentifier("selectVC") as! SelectViewController
selectVC.currentVenue = venueItems[indexPath.row]
presentViewController(selectVC, animated: true, completion: nil)
}
This segue works, however SelectView(3) doesn't have a navigation bar at the top although it is embedded in a separate NavigationController. If I hook it up to the other NavController in the IB, it adopts/becomes the third tab in the BarTabController. I don't want that.
How do I hook it up so that there is a NavBar (with a back button that will go back to either view) but no Tab?
Also, there is a button on SelectView(3). When this button is tapped I'd like it to segue to FeedView(1) - while persisting some data ie 'pushing into the feed'. What kind of segue should I use for this? I've tried many combinations and ran into some strange bugs and I find View management very confusing.
Storyboard image below for reference
Views are in order from top to bottom (1-3):
In order to do this you need to fix your problem, you need to present the navigation controller which contains SelectView but not SelectView itself as you do now.
You should set a storyboard identifier to your 3'rd navigation controller and apply this change:
let selectNavigationController = self.storyboard?.instantiateViewControllerWithIdentifier("selectNavigationController") as! UINavigationController
let selectVC = selectNavigationController.topViewController as! SelectViewController
selectVC.currentVenue = venueItems[indexPath.row]
presentViewController(selectNavigationController, animated: true, completion: nil)
I am using didDeselectRowAtIndexPath to navigate through different Storyboards like:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let story = ["News","Video","Twitter","Request Info","More"]
let vc = self.storyboard?.instantiateViewControllerWithIdentifier(story[indexPath.row]) as NewsFeedTableViewController
self.presentViewController(vc, animated: true, completion: nil)
}
However, the Navigation Bar does not show up when I use this function. But, when I use segue, the Navigation Bar shows up.
Now the Problem is:
Cells in a tableView cannot segue more than 1 storyboard
Need Navigation Bar to Scroll in the App (which seems to need Segue)
Any solutions through this?
You are using presentViewController, that's why you are not getting the NavigationBar, it presents the view modally. Instead of that pushViewController like:
self.navigationController?.pushViewController(vc, animated: true)
Probably in your storyboard the segue type will be push, that's why you are getting the Navigation Bar.
You might be interested in the following:
presentViewController:animated:completion:
ViewController Programming Guide for iOS
You are presenting the next view controller, not pushing it. (at least in case 1) So you have a modal link and no nav controller !
You can either use .pushViewController or simply performSegue and make sure your segue type is push. I would go for the performSegue and change the identifier name in each switchcase.
And you can still pass data in the prepareForSegue
Better to call performSegue in didSelectRow. And perform actions in perpareSegue Method .