Hihi all,
I am trying to make use of tabbar control in my iphone application, I have a few enquiries regarding the control.
If i create a tabbar template project, in my application delegate, it loads all the 5 tab controllers during the launch of the application, will this cause any inefficiency of the memory usage?
Can I actually drag the tabbar control into each of my screen, and manually switch between screens with [self presentedViewController..] and [self dismissModalViewControllerAnimated...] methods?
What is the most efficient way of using tabbar in iphone app?
Thanks in advance!
:)
Even though I'm not sure what 'most efficient' means in your context, I'll try to explain 3. with explaining what I usually do when it comes to typical tabbar apps:
I don't go with the sample project, because there's so much magic (to me) in all that IB stuff (and I had hard experiences in trying, to combine tabbar controllers and navigation controllers).
I just set up a simple project, get rid of all IB stuff and do something like that in the app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSMutableArray *cons = [[NSMutableArray alloc ]init];
viewController = [[UITabBarController alloc] init];
int i = 0;
UIViewController *firstController = [[SomeViewViewControllerClazz alloc] init];
firstController = [[UITabBarItem alloc]initWithTitle:#"Een" image:nil tag:i];
[cons addObject:firstController];
[firstController release];
i++;
UIViewController *secondController = [[AnotherViewControllerClazz alloc] init];
secondController = [[UITabBarItem alloc]initWithTitle:#"Twej" image:nil tag:i];
[cons addObject:secondController];
[secondController release];
i++;
UIViewController *thirdController = [[WhateverViewControllerClazz alloc] init];
thirdController = [[UITabBarItem alloc]initWithTitle:#"Drej" image:nil tag:i];
[cons addObject:thirdController];
[thirdController release];
i++;
viewController.viewControllers = cons;
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
That way I've maximum freedom to do whatever I want with the controllers but also have the built in power of tabbars.
1.: That way I never had memory issues even though I load controllers right at the beginning.
2.: If the tabbar idea fits your app, use it as iOs provides it.
The answer of your enquiries are:
No, this will not cause any inefficiency of the memory usage. But you should release tab bar controller
You may be do this, But it is not good practice and when you call presentedViewController tab will be vanished (sorry for inappropriate term).
The most efficient way of using tabbar in iphone app is take a tabbar controller and add that tabBar view.
Related
I have no idea how to set up a menu based project in xcode 4.2.
Basically, the menu has 4 buttons in it each go to their own Navigation Controlled tableviews, but I'm not sure where to start with xcode 4.2.
In my previous application I have a main window that has the navigation controller in that, then there is a root view which sets up the 4 buttons and from there the tableview view controllers just get loaded into the navigation controller.
With xcode 4.2 I cannot seem to set the delegate of the main window, so I cannot figure this out.
So I am hoping someone understands what I am trying to do and can help me out or send me a example or tutorial or something. Thanks, any help would be greatly appreciated.
Here is how I setup my navigation controller and root view in the AppDelegate file. From there you can just add the buttons and so on just as before. If you mean to do it with the storyboard, it will be much easier. Let me know if I misunderstood the question though:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[self managedObjectModel];
[self managedObjectContext];
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.backgroundColor = [UIColor whiteColor];
RootViewController *controller = [[RootViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:controller];
[self.window setRootViewController:navigation];
[controller release];
[navigation release];
[self.window makeKeyAndVisible];
return YES;
}
You'll be fine with one UINavigationController. In your view with the 4 menu buttons just hide the UINavigationController.
Hide / Show UINavigationController
I've an iPhone app that is a navigation-based app.
The customer require to convert 60% of the app to be inside a global TabBar. (i.e. to include one tabbar in 60% from the app views)
So, what is the best practice to follow here?
Is it to include a TabBar using IB into the Window?
Or add change the navigation code cross the whole app and push a TabBarController instead of the regular ViewController?
Please provide me with ideas.
Thanks.
I used a new window-based application and put the following code:
The idea is that to create a UITabBarController and put on it the NavigationController instead of the ViewControllers.
And each navigationController will navigate to its own set of ViewContrllers.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UITabBarController* tabBarContoller = [[UITabBarController alloc]init];
Cross1VC* cross1VC = [[Cross1VC alloc]initWithNibName:#"Cross1VC" bundle:nil];
cross1VC.title = #"Cross 1";
UINavigationController* crossNav = [[UINavigationController alloc]initWithRootViewController:cross1VC];
crossNav.title = #"Cross";
[cross1VC release];
Part1VC* part1VC = [[Part1VC alloc]initWithNibName:#"Part1VC" bundle:nil];
part1VC.title = #"Part 1";
UINavigationController* partNav = [[UINavigationController alloc]initWithRootViewController:part1VC];
partNav.title = #"Part";
[part1VC release];
NSArray* viewControllers = [NSArray arrayWithObjects:crossNav, partNav, nil];
[tabBarContoller setViewControllers:viewControllers animated:YES];
//tabBarContoller.delegate = [[SomeDelegateHandlerClass alloc]init]; // assign, not retain
[self.window addSubview:tabBarContoller.view];
//[tabBarContoller release]; // make instance variable and release in dealloc
[self.window makeKeyAndVisible];
return YES;
}
I'm fairly new to Objective-C and iPhone programming so I apologize if this is a newbie question. I have a simple application that needs to go from one view, to another. The first view is a UIViewController. I set up the xib file in IB (i.e. dragged some buttons onto the window) and hooked up all the buttons (which all work). I then created another xib file and class (also a UIViewController) and hooked them up. When a button is pressed in the first view I want to load the second view. Here's the code that is supposed to be pushing the view:
-(IBAction)createAccount:(id)sender{
CreateAccountViewController*acctView = [[CreateAccountViewController alloc] initWithNibName:#"CreateAccount" bundle:nil];
[self.navigationController pushViewController:acctView animated:YES];
[acctView release];
}
But this does nothing. When I put print statements in the createAccount method those are printed (I can click the button any number of times and it never crashes) but the acctView is never pushed. When I print out the value of self.navigationController it returns null. It's even stranger because if I present the acctView modally then it works.
-(IBAction)createAccount:(id)sender{
CreateAccountViewController*acctView = [[CreateAccountViewController alloc] initWithNibName:#"CreateAccount" bundle:nil];
[self presentModalViewController:acctView animated:YES];
[acctView release];
}
This works just fine, but I don't want to use the view modally. I'm completely lost here. In the past couple of hours I've come across a lot of posts saying to do something with a UINavigationController and hook that up to my view, but how do I do that? Any help is greatly appreciated! Thanks.
It seems you haven't created a UINavigationController for your app.
Best thing would be starting from scratch with a new Xcode project, taking care of choosing a Navigation Based application. In this way you will get almost everything already set up for you.
If you don't like this approach, you can create programmatically your UINavigationController. Here you find a tutorial for doing that.
If you prefer more straight-to-the-point instructions, here they are:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MainPageDialog *overviewViewController = [[MainPageDialog alloc] initWithNibName:#"MainPage" bundle:nil];
self.navigation = [[[UINavigationController alloc] initWithRootController:overviewViewController] autorelease];
[overviewViewController release];
[window addSubview:[navigation view]];
[self.window makeKeyAndVisible];
return YES;
}
whereby self.navigation is a retained property in your appDelegate.
EDIT:
This answer was quite old, therefore an update:
If you are using ARC, you should be using a strong (vs. retain) property and you would not need the autorelease;
if you target iOS > 4.0 (which is also implied by the above point), you can use the rootViewController property in UIWindow and say:
MainPageDialog *overviewViewController = [[MainPageDialog alloc] initWithNibName:#"MainPage" bundle:nil];
self.window.rootViewController = [[[UINavigationController alloc] initWithRootController:overviewViewController] autorelease];
[overviewViewController release];
[window addSubview:[self.window.rootViewController view]];
[self.window makeKeyAndVisible];
without the need for any navigation property.
I have been working on a UINavigationController based application, using a UITableView for the rootview and Core Data for the data source.
Unfortunately I didn't plan ahead very well and now would like to implement tab bar navigation to the app on top of what I already have.
Can anyone recommend a simple way to do this? Or am I better off starting again with the TabBar based template and try to plugin my existing code?
Thanks guys!
Adam
Rather than start over, you may just want to create a tab-bar-based app and look at the code it produces, then try to do the same thing in your app.
You probably just need to change your application delegate's application:didFinishLaunchingWithOptions: method to look something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSMutableArray *viewControllers = [[[NSMutableArray alloc] init] autorelease];
// First tab
MyController *myController = [[[MyController alloc] init] autorelease];
mapViewController.navigationItem.title = #"First";
UINavigationController *myRootController = [[[UINavigationController alloc]
initWithRootViewController:myController]
autorelease];
myRootController.tabBarItem.title = #"First";
myRootController.tabBarItem.image = [UIImage imageNamed:#"MyControllerTab"];
[viewControllers addObject:myRootController];
// Second tab
MyOtherController *myOtherController = [[[MyOtherController alloc] init] autorelease];
myOtherController.navigationItem.title = #"Second";
UINavigationController *otherRootController = [[[UINavigationController alloc] initWithRootViewController:myOtherController] autorelease];
otherRootController.tabBarItem.title = #"Second";
otherRootController.tabBarItem.image = [UIImage imageNamed:#"OtherControllerTab"];
[viewControllers addObject:otherRootController];
// Create other tabs
// ...
// Tab bar
UITabBarController *tabBarController = [[[UITabBarController alloc] init] autorelease];
[tabBarController setViewControllers:viewControllers];
[self.window setRootViewController:tabBarController];
[self.window makeKeyAndVisible];
return YES;
}
If you want to plug in your existing navigation controller to one of the tabs on a tab bar, it's pretty simple - just define a new UITabBarController to serve as the root controller and have it load your navigation controller into a single tab. Then change your app delegate to load the tab bar controller instead of your navigation controller.
If, however, you want to pull out multiple controllers from your existing navigation stack, you might have to do a bit more work - find places where you call pushViewController:animated: to modify your navigation stack, and instead plug those view controller instances into tabs on your tab bar. Here's where it might be worthwhile to start from a fresh tab bar template and copy over existing controllers, depending on the complexity of your code.
Adam,
Not sure how much coding you've done already, but if you're not that familiar with connecting things in IB and setting delegates you might be better off starting over with a TabBarController template.
Here's what you do:
Define new IBOutlet for UITabBarController in AppDelegate and Add TabBarController to IB
Connect UITabBarController to IBOutlet in AppDelegate in IB
Set Delegate for UITabBarController in IB to AppDelegate
Change rootViewController to tabBarController in AppDelegate
Drag All ViewControllers into Tab Bar Controller in IB
Setup other Tabs using NavigationControllers or UIViewControllers depending on your design
Run, Fix, Repeat
So I feel like a serious rookie right now, but I have a problem I can't seem to figure out. I have a barebones app, with literally nothing in it except a login screen and a second view containing a tableview. When I add the second view after logging in (I have done this like 4 times before...), the table view goes through its delegates and appears that it's going to load, but something happens. I have enabled my NSZombies, and it appears to be deallocating the new view, right before it appears.
After tracing through it, and building up again piece by piece, it appears to happen after I wire the table to the view as the datasource/delegate in IB. I have set the view as a UITableViewDelegate, and the methods indeed get fired. Does anyone have any idea what might be causing this behavior?
Have you added the 'second'view to an exisitng view using addSubview: or added it to some form of UINavigationController or UITabBarController? When you do this it will automatically increase the retain count and whatever code you have releasing the view won't cause is to be deallocated.
In my AppDelegate application:didFinishLaunchingWithOptions I have something like;
LoginViewController *login = [[LoginViewController alloc] init];
[login setDelegate:self];
loginNavController = [[UINavigationController alloc]
initWithRootViewController:login];
[window addSubview:[loginNavController view]];
And then once login has occured (and succeeded using a protocol/delegate to send the message back to AppDelegate) I call this code;
UIViewController *newView1 = [[UIViewController alloc] init];
UIViewController *newView2 = [[UIViewController alloc] init];
UIViewController *newView3 = [[UIViewController alloc] init];
myTabBarController = [[UITabBarController alloc] init];
myNavController = [[UINavigationController alloc]
initWithRootViewController:newView1];
// nav controller now retaining
[newView1 release];
NSArray *viewControllers = [NSArray arrayWithObjects:myNavController,
newView2,
newView3,
nil];
[myTabBarController setViewControllers:viewControllers animated:YES];
[[myTabBarController view] setFrame:[[UIScreen mainScreen] applicationFrame]];
[window addSubview:[tabBarController view]];
// tab bar controller now retaining
[newView2 release];
[newView3 release];
// remove login from application
[[loginNavController view] removeFromSuperview];
The AppDelegate has the following declared in the header file;
LoginViewController *loginViewController;
UITabBarController *myTabBarController;
UINavigationController *myNavController;
In the dealloc method for the AppDelegate these are released.
This gives me my login page and then when that has processed my views with a top nav all controlled using the bottom tab bar.
Hope this helps in some way.
You have either too many release (or autorelease) calls - or not enough retain calls - in your view loading/transitioning code, but it's impossible to be more specific without seeing that code.
What's probably happening is the autorelease pool is being flushed between your view loading and your view being shown, and that's what's leading the behaviour you describe.