I’m developing a first iPhone app for iOS 4.x/5.0 and have some confusions on how to comply with the recommended Apple guidelines. I have also attached code snippet.
Here is the scenario:
When the app loads, I want to show the following functionalities in the bottom of the screen: Test, Settings. My first question is do I have to go with a UISegmentedControl or UITabBar? The trickiest part is I don’t want the first “Test” tab/button to be selected automatically. I want the user to select the tab/button. Until that happens, I want a timer that runs showing some text. I tried to use a UITabBar and when the app loads, the first “Test” tab is selected and the associated ViewController is shown by default. I circumvented this by pushing a “root view controller” in the “didFinishLaunchingWithOptions” method in the AppDelegate.m. This works and when I click on the “Scores” tab, it pops the “root view controller” and pushes the “test view controller”. But if I select the “Settings” tab immediately after the app loads and click on the “Test” tab, the view controller for the “Test” tab is not loading at all, but the “main view controller” is still displayed. I also have a UINavigationController in place on the “Test” tab and I hide it in the “viewDidAppear” event. I also want to eliminate the animation (pushing back) when I click on the “Test” tab.
My confusions are:
-
Can I replace the UINavigationController with some other control to let the user click on a “Start/Stop” button (displayed on the top) when in the “test view controller”?.
-
Is there a click event on the tabs in the UITabBar for each of the tabs?
-
I wanted to do everything from code (except adding controls) to ViewControllers. It looks confusing to me to use IB to do the same thing. Is this is a bad approach?
The following is the code snippet:
AppDelegate.m
#import "NavTabTestAppDelegate.h"
#import "RootViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h"
@implementation NavTabTestAppDelegate
@synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RootViewController *rootViewController = [[RootViewController alloc ] initWithNibName:@"RootViewController" bundle: nil];
[rootViewController.view setBackgroundColor:[UIColor blueColor]];
// [rootViewController setTitle:@"RootViewController"];
FirstViewController *firstViewController = [[FirstViewController alloc ] initWithNibName:@"FirstViewController" bundle: nil];
[firstViewController.view setBackgroundColor:[UIColor yellowColor]];
[firstViewController setTitle:@"FirstViewController"];
SecondViewController *secondViewController = [[SecondViewController alloc ] initWithNibName:@"SecondViewController" bundle: nil];
[secondViewController.view setBackgroundColor:[UIColor redColor]];
[secondViewController setTitle:@"SecondViewController"];
//create the navigation controller and use NavRootController as its root
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:firstViewController];
//create an array of views that will be passed to our tabbar
NSArray *viewsArray = [NSArray arrayWithObjects:nav, secondViewController, nil];
//Now create our tab bar controller
UITabBarController *tabbarController = [[UITabBarController alloc] init];
//then tell the tabbarcontroller to use our array of views
[tabbarController setViewControllers:viewsArray];
[nav pushViewController:rootViewController animated:NO];
//nav.view.hidden = YES;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
//then the last step is to add the our tabbarcontroller as subview of the window
self.window.rootViewController = tabbarController;
return YES;
}
RootViewController.m (added the following code)
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:animated];
// NSLog(@"Inside RootViewController.m viewWillAppear %@", animated);
}
- (void) viewWillDisappear:(BOOL)animated{
// NSLog(@"Inside RootViewController.m viewWillDisappear %@", "Done");
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
FirstViewController.m (added the following code to prevent the animation but didn’t work)
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:NO];
[self.navigationController setNavigationBarHidden:NO animated:NO];
// NSLog(@"Inside FirstViewController.m viewWillAppear %@", animated);
}
- (void) viewWillDisappear:(BOOL)animated{
// NSLog(@"Inside FirstViewController.m viewWillDisappear %@", "Done");
[super viewWillAppear:NO];
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
NSLogs throws exception when I click on a tab (BAD_ACCESS). Couldn’t figure out why.
I come from a Windows developer background and I apologize for the long post. Please help.
Thanks.
I think you’re missing the point of UITabBarController. Its job is to let the user select one of several different views, and it manages the view controllers corresponding to those views. One of the views will always be selected — it really doesn’t make sense to have no tab selected. If you want the “tabs” to do something other than select a view, you should use something else, such as UIToolbar or perhaps UISegmentedControl.
I had a hard time grokking what you’re trying to do with the navigation controller, so it’s hard to say whether or not you can replace it. You should understand, though, that UINavigationController is a view controller, not a control. If you’re just talking about the navigation bar that’s provided by the navigation controller, then sure, you can display that or not depending on your preference.
The tab bar delegate should implement the UITabBarDelegate protocol, which includes
– tabBarController:didSelectViewController:.Depends on who you ask. Most experienced Objective-C programmers use IB when it’s appropriate, i.e. just about any time you need to define a relatively static user interface.
Some people prefer not to use IB, but it seems to me that most of those folks never really took the time to learn how to use IB. You should do whichever you prefer.
I’d say that avoiding a useful tool because you don’t understand it might be reasonable in the short term, but is a poor approach over the long term. When you’re just learning to program on a whole new platform, it’s quite reasonable to limit the number of things you need to know. IB really isn’t complicated, though, and it’s very useful. If you don’t use it right now, make a note to yourself to spend some time working with it in the future.