Switching UINavigationViewController to UITabBarController with Segues - ios

I am changing my app to use UITabBarController instead of UINavigationViewController. I replaced controllers accordingly and app launches with tabs successfully. Later in the code I came across some difficulties using segues where lines like
[self performSegueWithIdentifier:#"ImageViewController" sender:self];
won't work producing error
"Push segues can only be used when the source controller is managed by an instance of UINavigationController"
When I embedded UINavigationController into the initial FirstViewController, line above worked fine. I need that line to switch between views and pass some data to another view controller.
The problem is that using segue identifier to go to SecondViewController hides TabBar navigation (unless I wrap SecondViewController in UINavigationController again and so on). That is not the solution.
Question: How to use UITabBarController and still take advantage of segues while keeping tab navigation visible?

"Push segues can only be used when the source controller is managed by an instance of UINavigationController"
Sounds to me like you are using a push segue somewhere outside a navigation controller. Try to select all "segue bubbles" in interface builder that are not inside a navigation controller:
and check the segue's style in the right pane:
If the style is set to the value push as shown above change it to modal or custom:

There is something wrong with your connections. If you are using interface builder (storyboard) then your connections should look like this. See pic
Notice you are missing UINavigation Title headers. Also the gray area below on each view controller means that space is reserved for images for UITabBarController
Another problem is your UIToolBar. Looks like its sitting on top of where UITabBar will be displayed. That may/may not get your app rejected by apple since you already have a UINavigationController and UITabBarController. If you need more buttons/options on that page make them UIButtons instead.

Related

Can I use a single navigation controller to the multiple storyboards?

I am using two storyboards Main and StoryboardA. For Main.storyboard i have embedded a navigation controller. From Main.storyboard i need to go the storyboard StoryboardA. So for acheiving this i have given a storyboard reference. But the problem is i am not getting the back button on the StoryboardA . It seems the StoryboardA is presenting itself instead of getting pushed. Please see the below image: So My question is do we need to use another navigation controller for StoryboardA?
Main Storyboard:
Second Storyboard:
I seem to have found a solution mired in all of these solutions for old versions of iOS and Xcode. In short, in your second storyboard, mark your first view controller as "Is Initial View Controller", not the navigation controller.
Your navigation controller will remain and still point to your first view controller. I wonder about downstream issues yet to appear but others seem to have had success.
Have you added segue as push ? On control click - > Select segue type as Push .It should work fine.
You can use a RootViewController for many StoryBoards but you can use only one Storyboard for a NavigationController

Show(e.g. Push) from a viewcontroller to a navigation controller works?! Why?

So I am new to IOS programming and I am using the Swift language.
After doing a couple of beginner apps. I have had some trouble on figuring the difference between the Show(e.g. Push) and the deprecated Push segues.
What I want to do is to Show/Push from a ViewController A(embeded with Navigation Controller B ) to a Navigation Controller C (containing a View Controller D).
Since when I disable the "Use size classes", the Push segue doesn't work and will report error "pushing to a navigation controller is not supported". This error makes sense since you can only push regular view controllers.
However when I enable the "Use size classes" (which turns the Viewcontroller to a square instead of a rectangle), I was able to Show(e.g. Push) to a navigation controller, which really confuses me.
So what's the main difference between the Show(e.g. Push) and the deprecated Push? As to my knowledge there is no major functional difference but the fact seems to prove me wrong and makes me confused..
Update:
I have recreated the behavior you observe. The Show (e.g Push) segue does indeed work from one viewController embedded in a navigationController to a second viewController embedded in a different navigationController.
Note that when the push happens, the second viewController slides in in the normal push way, and a back button appears that takes you back to the first viewController. This tells you that the second viewController is actually being pushed onto the stack of the first navigationController. So instead of giving you the error message, it is simply ignoring your second navigationController.
When using a navigationController, only the first viewController is imbedded in a navigationController. You don't have to embed subsequent viewControllers in a navigationController, because when you wire up the Push segue from a previous viewController in the navigationController's stack, the Storyboard will recognize that this new viewController is controlled by a navigationController and it will add the navigationBar at the top.
Original Answer:
A Show (e.g. Push) segue is an Adaptive Segue. It chooses the correct segue type based upon the situation.
If your source viewController is in embedded in a Navigation Controller, it does a Push.
If your source viewController is in a SplitViewController without a NavigationController, it does a Replace.
In all other cases, it does a Modal segue.
So, it works because it is actually doing a Modal segue in your case, which works if you aren't using size classes. You will notice that the presented viewController actually slides in from the bottom which is a tell-tale sign of a Modal segue.
You can find information about it here:
Backward Compatibility of Active Segues.

How to link a separate storyboard to each particular tab in uitabbarcontroller?

I have an app which has 5 major user flows..each flow is a few screens linking to each other...so each flow warranties its own storyboard. Each storyboard starts with a custom view controller that is embedded in a navigation controller. So far so good.
Now all of this is "stitched" together via a UITabBarController. This is the most default UI design ever known to iOS.
But turns out I don't really know how to link from tabbarcontroller, which is in its own storyboard (that is set as the main one on code project) to any of the other storyboards.
This problem looks so! simple, so I think I am missing something utterly obvious, but I just can't figure out how to do it.
So how do I link from tab bar controller in storyboard 1 to the initial view controller in storyboard 2 when a tab is tapped?
You should do this in code. You can have the tab bar controller (tbc for short) and the controller in the first tab in the app's main storyboard, and in the app delegate, instantiate the other controllers using instantiateInitialViewController. Create a mutable array by copying the tbc's viewController array, add the other controllers you instantiated to it, and then set that array as the tbc's viewControllers array.
You have to add your viewcontroller programmatically in tabbar.

Use of differenct view controllers

i'm curious about what's the best way to plan the controllers for my app.
i want my main screen to have 3 button.
1) should open a nav controller with details view
2) should open a controller with other buttons that lead to others controllers
3) should open a tab bar with 2 pages ( or eventually use a switch to change page instead of the tab bar)
this is the schema of what i want
http://i59.tinypic.com/2rrvrd4.png
Is it a correct schema or i should use my controllers differently? will apple reject an apple with such schema?
thanks
As #Fogmeister pointed out in the comments, going for a UITabBarController as the main interface for your app actually seems to be a more appropriate solution here.
However, you can go with the interface that you described, but then you should keep in mind that with your current setup, you are not only using UINavigationController in the first case, but your whole navigation system is still built upon UINavigationController in the following way:
Your app has one instance of UINavigationController.
Your initial UIViewController (the one with the three buttons), is the rootViewController of your UINavigationController.
You can navigate to the other view controllers using [self.navigationController pushViewController:newViewController] (or performSegue if you prefer using Storyboards).
In the case of your third view controller, you are pushing a UITabBarController onto the navigation controller's view controller stack, this UITabBarController needs to be initialized with the two view controllers that it is going to display before it gets pushed onto the stack.

UITabBar tab pushes new ViewController

Let's say I have 4 items in my UITabBar: A B C D.
Via the delegate methods, D pushes a new viewController from the UITabBar's navigationController, (removing the tabBar for that one view).
This works fine, but how can I keep the UITabBar from showing a blank view for D when going back from the new view?
I tried setting the selectedIndex to the previous index on push, but that just hangs the app (seems to work fine for modals, just not when pushing.)
If I interpret this correctly, when you're pushing a view as a result of selecting a tab, you're simultaneously changing the tab that's selected. This is probably trying to then change the view hierarchy that you're currently pushing a view on (that would be the result of selecting the other tab that you're trying to set it to). So it's probably crashing because it's replacing a view that's in the process of being displayed.
Also, from the sound of it you're using a UITabBarController inside of a UINavigationController. Apple says that you're not supposed to place a UITabBarController inside another view controller. The following is taken from Apple's docs on UITabBarController:
When deploying a tab bar interface, you must install this view as the root of your window. Unlike other view controllers, a tab bar interface should never be installed as a child of another view controller.
If this is the case, you should redesign your app so that you're not containing the tab bar controller in any other view controllers, or your app may behave oddly or stop working at some point.
If you wanted to make things behave exactly how you want them to, you could use a UITabBar directly, and implement your own UITabBarDelegate.

Resources