Need help with the tab bar and tab bar controller - objective-c

My iPhone app has a login page (shocker i know) but when the user successfully logs in, I want a view with a tab bar at the bottom to load and populate the buttons with data from the specific user. I can not find any tutorials on the tab bar, just the tab bar controller and from what i've read and seen, you can only have a tab bar controller on the MainWindow.xib. If thats not true, please show me how to have a tab bar controller on a view other that the main window. This is driving me nuts. Beer on me for a solution. Thanks

I have the same exact thing going on in my app and I can sympathize with you. There really isn't much to go on out there.
For me, it starts in your AppDelegate. I would validate the login info there, if it was good, push out the tabbarcontroller. If not, just present the logincontroller instead. It can be a tad tricky, but if you start there, you should be able to use everything else to get what you need.
Use the AppDelegate to determine which controller to push. When you push the login and it is good, call back to your appdelegate to push the tab bar controller and kill off the login.
Hope this helps. Good Luck.

You certainly can have a tab bar controller in other places besides MainWindow.xib. An example of one being created programattically, is in View Controller Programming Guide for iOS. See the section on Creating a Tab Bar Interface Programmatically.
Now, you've probably seen this already, but the point is even though Apple's example is in applicationDidFinishLaunching, you could do it anywhere you launch a view controller, like in response to a button click.
A few things to consider though:
Tab bar view controllers aren't meant to be embedded inside a navigation controller (i believe it would give you errors). it's the other way around is recommended. It might make more sense to present a tab bar view controller modally.
In your specific case, it sounds like the best thing would be to keep it simple by letting the tab bar be the root view controller in the main window after all, and having your login screen be automatically popped up after launch (i.e present it modally) then after proper login, dismiss the log in screen to reveal the tab bar controller that was there all along.

Related

UINavBarController connecting the same UIViewController to multiple navigation controllers

I have a storyboarded app with a chain of tableviews followed by a detail view. Kind of the classic iPhone app. There are 4 tabs and each one leads to a navigation controller.
The issue is I really want to avoid unnecessary glue code since the app is basically finished. If it was possible to connect the Search and Favorites (bottom two off the tab bar) controller as 'Root View Controllers' to the same UIViewController I would be done. However, this won't work since a view controller can only be the root view controller to one tab. So as you can see I've instituted two dummy UIViewControllers that forward you to the UIViewController in the middle. Now, unfortunately, I have to write code to make that central view controller a fake root view controller to disable the appearance of the back button, and prevent popping to the blank root when you double-tap the tab bar.
Has anyone got a more elegant solution?
This appears to be a flaw in Storyboards. One workaround would be to use simple view controllers for each navigation controller's rootViewController. Put a UIContainerView in each that points to the UIViewController you want to share.

Storyboard with NavigationController and TabController

It seems like this should be easy to figure out, but I haven't had any luck this afternoon. I threw together this quick, simplified storyboard mockup of my problem.
Basically, I would like the table view controllers below to also be in a tab bar controller (in addition to the already present navigation controller). The tabs would switch between the two table view controllers.
Right now, the view controller with the buttons acts as a sort of menu. Each button leads to one of the table view controllers. Ideally this view controller would not have the tab bar visible, and would only be reachable from back buttons on the nav bars of the table view controllers.
I've tried a few different ways of embedding into a tabbarcontrollers but none of them produce the desired result:
-I've tried selecting both table view controllers and embedding those in a tab view controller. The tabbar doesnt show up in simulator, and the 'unreachable scene' warning appears.
-I've tried embedding the initial nav controller into a tabbarcontroller. This creates a tab entry for the first 'menu' page. It also causes issues with push segues once I connect the tableviews to the tabview.
I would be fine implementing some programmatic options on top of the storyboard, I just chose storyboarding for this project since it's a relatively simple presentation of data.
What is the proper way of going about this? Thanks!
A tab bar controller needs to be the root view controller of your view hierarchy. It goes against the HIG and Apple's standards to put a tab bar controller inside of any other type of container controller.
From the Apple docs:
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.
So, the bottom line here is you need to rethink your design. One option would be to set the UITabBarController as the root view of your window, and then have each of your UITableViewControllers inside of a UINavigationController, which is placed inside of the UITabBarController. In this way, you still get the navigation bar, and stay within Apple's design guidelines (you also won't get those pesky warnings, and Apple may even be throwing an exception nowadays if you try to install a UITabBarController as anything other than the root view of the window).
I accept JMStone answer but we might get into situation where we need to put tab bar controller inside other controller especially table view controller.
Please refer Storyboard navigation controller and tab bar controller
and also the good example by Matthjin: http://cl.ly/VQLa
Hopes it help some one who want to put tab bar controller inside table view controller and wants proper navigation.

Modal UINavigationController hides although not dismisses

Okay, so I'm building an universal iOS app with an initial login view (view controller named LoginVC), just a plain simple UIViewController. If the login is successful the app segues to an navigation controller (MainNavigationVC). I created this segue through the storyboard gui of XCode, so no programmatic creation of the nav controller is done. The nav controller is presented modally in fullscreen, so the rest of the app is run atop the login view, with this nav controller as the centerpiece of everything.
The navigation controller contains a view (with a view controller named UserStartPageVC), and in its navigation bar is a logout button. This button sends an target action to UserStartPageVC, with the goal of dismissing the nav controller thus bringing the user back to the login view.
So far everything works fine. I can login and use the app as intended. But! When I log out and then re-login XCode tells me this:
Warning! Attempt to present <MainNavigationVC: 0x753110> on
<LoginVC: 0x756fcf0> while a presentation is in progress!
I suppose this means that the login view is trying to modally display a MainNavigationVC navigation controller, but another one is already displayed, right? But how? Can a view be presented without showing?
And how can I get rid of the old nav controller when logging out? I've tried several ways of dismissing the modal view, for instance:
from within UserStartpageVC running
[x dismissViewControllerAnimated:YES completion:NULL]
[x dismissModalViewControllerAnimated:YES]
where x is either self, self.parentViewController or self.presentingViewController.
setting the LoginVC as a property in UserStartpageVC and running
[self.loginVC dismissViewControllerAnimated:YES completion:NULL]
and so on.
All of the tested calls actually brings me back to the login screen, so it's kind of working.
Any ideas? Relevant code samples can be provided if necessary, I just couldn't figure out which pieces that were of interest. The seguing to the navigation controller has no code (except for a performSegueWithIdentifier:sender:), and the code for dismissing it is the part I cannot seem to get straight.
As a sidenote. So far this isn't a REAL problem; the app runs, and it IS possible to logout and re-login without any other side-effects than an error message in XCode. But I suppose this will be a memory leak if users logout and login multiple times, and I'm not in the mood of an unnecessary rejection from Apple.
I discovered another way to get the exact same error message. Lucky me!
If you created a segue at one point and had it tied to a button (click button -> new view) and then later give that segue a name and invoke it directly using
[self performSegueWithIdentifier:#"identifierName" sender:self];
then you can get this error because you can effectively trigger the segue twice. I thought making the button invoke an IBAction would turn off the segue I had set up in the first place, but apparently not. Hitting the button triggered the segue twice, but after I deleted the segue and re-created it as a manual segue on the view with the same identifier then I was able to invoke it via the above code and not get the warning message.
Hoopla! My bad.
Seemed I had set up the notification observing from the login API call in a stupid way. For every time the user triggered a login (or re-login), it added itself as an observer for the notification; the result was that it performed one more segue for every time a login was done.
And doing multiple segues at the same time, is... well, obviously bad.

Button push to specific tab bar item?

I thought this is quite simple but I can't seem to find the answer. I have a view controller with 3 buttons, one of these buttons has a push segue to a tab bar controller. When pressed I presume it loads the '0th' tab item which is the fine for the first button but how do I then get the other two buttons to push segue to the other two tabs?
I have read a lot of articles but none of them seem to have the answer that I'm looking for. I already have the tab bar controller and all the sub-views created in the storyboard, I just can't seem to get an instance of the UITabBarController.
I have 2 logical ways of doing it in my mind but I am quite new to objective-c and can't work either of them out for the life of me.
The first is to programmatically load the uitabcontroller and set which item I'd like to load but I can't seem to find a way of invoking an already existing tab bar controller. Something like this (I know it loads a random view which is not what I exactly want):
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:view1ViewController];
My other idea was to either override / hijack the segue or the load event of the tab bar controller and find out who called the segue and then if they are one of my other buttons and then switch to the relevant tab item using:
[myTabBarController setSelectedIndex:index]
I just can't seem to put it all together. I suspect the latter idea requires app delegates which I don't quite understand yet.
I apologise for this in advance - I realise that I'm in completely way over my head! (btw... I have moderate PHP and C# OOP experience so I understand 'some' things.)

Why does the iPad stop auto-rotating when I start overlaying View Controllers?

I have a fairly hefty project, where I am loading a few view controllers, one after the other. First, a splash screen, followed by a menu system, and when the user clicks on the menu it goes through to an article view controller.
Putting all these in with shouldAutorotate... set to YES for all rotations, this works fine. However, I have a menu bar I need to slide down over the top when a tap gesture has been recognised. I have one for the main menu, and one for the article view.
If I put one of these in, it still auto-rotates fine. However, as soon as I put the next one in, the auto-rotate stops working. I've tried putting the menu bars in the app delegate, as well as nesting them inside the menu/article view controllers. The Menu Bar view controller also has shouldAutorotate... set to YES. In fact, every single view controller in the project (all 7 of them) have it set to YES. And yet, when I add my second Menu bar controller, it stops auto-rotating. It doesn't even trigger the "shouldAutorotate" method to ask it.
The code is way too large to post here, but if you'd like to see anything in particular then just ask. I'm totally stumped! I'm about to pull the menu bars out of their view controller and code them up in each of the view controllers individually. This will be a hideous amount of code duplication, but I can't think of any other way round it!
Any ideas? Thanks!
The answer appears to be... Don't put view controllers within other view controllers! One view controller = one screen, seems to be the rule. I have a lot to learn!