UITabBarItems in UITabBar show after I click the item not when application launches - iphone

This application I'm writing has a problem.
I'm setting up the UITabBar in my application window and set the icons in the view files.
But when i run the app, the first icons show up (because the view is loaded I guess) and the other icons do not show up until I click them.
Do i need to implement self.tabBarItem in some other method not viewDidLoad?
Thanks in advance to everyone!
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
tabBar = [[UITabBarController alloc] init];
SubscriptionsController *subscriptionsController = [[SubscriptionsController alloc] init];
FavoritesController *favoritesController = [[FavoritesController alloc] init];
CategoriesController *categoriesController = [[CategoriesController alloc] init];
TagsController *tagsController = [[TagsController alloc] init];
HelpScreenController *helpScreenController = [[HelpScreenController alloc] init];
tabBar.viewControllers = [NSArray arrayWithObjects:
subscriptionsController,
favoritesController,
categoriesController,
tagsController,
helpScreenController,
nil
];
[window addSubview:tabBar.view];
// Override point for customization after application launch.
[window makeKeyAndVisible];
return YES;
}
//The View
- (void)viewDidLoad {
[super viewDidLoad];
tabIcon = [[UITabBarItem alloc] initWithTitle:#"Abonime" image:[UIImage imageNamed:#"subscr.png"] tag:0];
self.tabBarItem = tabIcon;
[tabIcon release];
}

I think you should set the tabBarItem property in a view controller's designated initializer (judging from your code, it must be -init for each of the controllers). In fact, the tab bar controller is smart enough to load the views on demand, that is, the tabBarItem property should be set before viewDidLoad gets sent.
Also, you seem to be leaking all the view controllers. To fix that, do the following:
SubscriptionsController *subscriptionsController = [[[SubscriptionsController alloc] init] autorelease];

Correct. The icons don't show up because the view (other than the first one, isn't loaded yet). And doesn't get loaded until you tap a view because viewDidLoad isn't called until then.
Remove the code in the individual UIViewControllers viewDidLoad and Do this...
NSArray *controllers = [NSArray arrayWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:#"SubscriptionsController", #"class", [UIImage imageNamed:#"btn_tax.png"], #"icon", #"Abonime", #"title", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"FavoritesController", #"class", [UIImage imageNamed:#"btn_tax.png"], #"icon", #"Abonime", #"title", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"CategoriesController", #"class", [UIImage imageNamed:#"btn_tax.png"], #"icon", #"Abonime", #"title", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"TagsController", #"class", [UIImage imageNamed:#"btn_tax.png"], #"icon", #"Abonime", #"title", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"HelpScreenController", #"class", [UIImage imageNamed:#"btn_tax.png"], #"icon", #"Abonime", #"title", nil],
nil];
NSMutableArray *controllerArray = [NSMutableArray array] ;
for (NSUInteger i = 0; i < [controllers count]; i++)
{
id newClass = [[NSClassFromString([[controllers objectAtIndex:i] objectForKey:#"class"]) alloc] init];
UITabBarItem *tabItem = [[UITabBarItem alloc] init];
tabItem.image = [[controllers objectAtIndex:i] objectForKey:#"icon"];
tabItem.title = [[controllers objectAtIndex:i] objectForKey:#"title"];
tabItem.tag = i;
[(UIViewController*)newClass setTabBarItem:tabItem];
[tabItem release];
[controllerArray addObject:newClass];
[newClass release];
}
tabBar.viewControllers = controllerArray;

Related

Putting a ViewController on top of a TabBarController

Basically I want to make a login screen in my iPhone app before I show my TabBarController. I tried the following approach, adding first to the window subview my TabBarController and on top my LoginViewController. What am I doing wrong or should I do it completely different?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
NSMutableArray *tabItems = [[NSMutableArray alloc] initWithCapacity:2];
DefaultViewController *dvc = [[DefaultViewController alloc] init];
UINavigationController *dvc_nc = [[UINavigationController alloc] initWithRootViewController:dvc];
dvc_nc.tabBarItem.title = #"Home";
//dvc_nc.tabBarItem.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Default" ofType:#"png"]];
[tabItems addObject:dvc_nc];
[dvc release];
[dvc_nc release];
OptionsViewController *ovc = [[OptionsViewController alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *ovc_nc = [[UINavigationController alloc] initWithRootViewController:ovc];
ovc_nc.tabBarItem.title = #"Option";
//ovc_nc.tabBarItem.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Option" ofType:#"png"]];
[tabItems addObject:ovc_nc];
[ovc release];
[ovc_nc release];
UITabBarController *tbc = [[UITabBarController alloc] init];
tbc.viewControllers = tabItems;
self.tabController = tbc;
[tabItems release];
[tbc release];
[self.window addSubview:self.tabController.view];
LoginViewController *lvc = [[OptionsViewController alloc] init];
UINavigationController *lvc_nc = [[UINavigationController alloc] initWithRootViewController:lvc];
[self.window addSubview:lvc_nc.view];
[lvc release];
[lvc_nc release];
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
NSMutableArray *tabItems = [[NSMutableArray alloc] initWithCapacity:2];
DefaultViewController *dvc = [[DefaultViewController alloc] init];
UINavigationController *dvc_nc = [[UINavigationController alloc] initWithRootViewController:dvc];
dvc_nc.tabBarItem.title = #"Home";
//dvc_nc.tabBarItem.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Default" ofType:#"png"]];
[tabItems addObject:dvc_nc];
[dvc release];
[dvc_nc release];
OptionsViewController *ovc = [[OptionsViewController alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *ovc_nc = [[UINavigationController alloc] initWithRootViewController:ovc];
ovc_nc.tabBarItem.title = #"Option";
//ovc_nc.tabBarItem.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Option" ofType:#"png"]];
[tabItems addObject:ovc_nc];
[ovc release];
[ovc_nc release];
UITabBarController *tbc = [[UITabBarController alloc] init];
tbc.viewControllers = tabItems;
self.tabController = tbc;
[tabItems release];
[tbc release];
[self.window addSubview:self.tabController.view];
LoginViewController *lvc = [[OptionsViewController alloc] init];
UINavigationController *lvc_nc = [[UINavigationController alloc] initWithRootViewController:lvc];
[self.tabController presentModalViewController:lvc_nc animated:no];
[lvc release];
[lvc_nc release];
return YES;
}
I would use two different views. One will handle the login proccess and one is your "Logged in view" that provides the features of your app. When your app starts up, you add the login view, check username/password and when the login went fine you switch to your second view.

how to edit an NSMutableArray data?

I have this NSMutableArray
sections = [[NSMutableArray alloc] init];
[sections addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:#"Electricity",#"Type",#"0",#"Count", nil]];
[sections addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:#"Water",#"Type",#"0",#"Count", nil]];
[sections addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:#"Mobile",#"Type",#"0",#"Count", nil]];
[sections addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:#"Internet",#"Type",#"0",#"Count", nil]];
[sections addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:#"Fixed Line",#"Type",#"0",#"Count", nil]];
and lets say a user choose to change Water count from 0 to 10 how to do that?
[[sections objectAtIndex:1] setObject:#"10" forKey:#"Count"];
One more thing. When you create objects with alloc+init, you should release them yourself. So for each NSMutableDictionary you have a memory leak (in your code).
Use either [[[NSMutableDictionary alloc] initWithObjectsAndKeys:..., nil] autorelease]; or [NSMutableDictionary dictionaryWithObjectsAndKeys:..., nil]; (of course, you can make something like for (NSMutableDictionary *dict in sections) [dict release]; later, but this looks ugly).

iPhone : Display popOver from tabBarItem

I wonder how I can display a popOver from a tabBarItem ?
Here is how I manage my tabBarController :
tabBarController = [[UITabBarController alloc] init];
searchSplitViewController = [[UISplitViewController alloc] init];
searchRoot = [[[EI_iPad_Home_Root_ViewController alloc] init] autorelease];
searchDetail = [[[EI_iPad_Home_Detail_ViewController alloc] init] autorelease];
searchRootNav = [[[EI_Navigation_ViewController alloc] initWithRootViewController:searchRoot]autorelease];
searchDetailNav = [[[EI_Navigation_ViewController alloc] initWithRootViewController:searchDetail] autorelease];
searchSplitViewController.viewControllers = [NSArray arrayWithObjects:searchRootNav, searchDetailNav, nil];
searchSplitViewController.delegate = searchDetail;
favoritesSplitViewController = [[UISplitViewController alloc] init];
favoritesRoot = [[[EI_iPad_Favorites_Root_ViewController alloc] init] autorelease];
favoritesDetail = [[[EI_iPad_Favorites_GeneralDetail_ViewController alloc] init] autorelease];
favoritesRootNav = [[[EI_Navigation_ViewController alloc] initWithRootViewController:favoritesRoot]autorelease];
favoritesDetailNav = [[[EI_Navigation_ViewController alloc] initWithRootViewController:favoritesDetail] autorelease];
favoritesSplitViewController.viewControllers = [NSArray arrayWithObjects:favoritesRootNav, favoritesDetailNav, nil];
favoritesSplitViewController.delegate = favoritesDetail;
agencySplitViewController = [[UISplitViewController alloc] init];
agencyRoot = [[[EI_iPad_Agency_Root_ViewController alloc] init] autorelease];
agencyDetail = [[[EI_iPad_Agency_GeneralDetail_ViewController alloc] init] autorelease];
agencyRootNav = [[[EI_Navigation_ViewController alloc] initWithRootViewController:agencyRoot]autorelease];
agencyDetailNav = [[[EI_Navigation_ViewController alloc] initWithRootViewController:agencyDetail] autorelease];
agencySplitViewController.viewControllers = [NSArray arrayWithObjects:agencyRootNav, agencyDetailNav, nil];
agencySplitViewController.delegate = agencyDetail;
editoSplitViewController = [[UISplitViewController alloc] init];
editoRoot = [[[EI_iPad_News_Root_ViewController alloc] init] autorelease];
editoDetail = [[[EI_iPad_News_Detail_ViewController alloc] init] autorelease];
editoRootNav = [[[EI_Navigation_ViewController alloc] initWithRootViewController:editoRoot]autorelease];
editoDetailNav = [[[EI_Navigation_ViewController alloc] initWithRootViewController:editoDetail] autorelease];
editoSplitViewController.viewControllers = [NSArray arrayWithObjects:editoRootNav, editoDetailNav, nil];
editoSplitViewController.delegate = editoDetail;
searchSplitViewController.tabBarItem.title = NSLocalizedString(#"TabBar_search_label",nil);
searchSplitViewController.tabBarItem.image = [UIImage imageNamed:#"tabBar_search_icon.png"];
favoritesSplitViewController.tabBarItem.title = NSLocalizedString(#"TabBar_favorite_label",nil);
favoritesSplitViewController.tabBarItem.image = [UIImage imageNamed:#"tabBar_favorite_icon.png"];
agencySplitViewController.tabBarItem.title = NSLocalizedString(#"TabBar_agencies_label",nil);
agencySplitViewController.tabBarItem.image = [UIImage imageNamed:#"tabBar_agencies_icon.png"];
editoSplitViewController.tabBarItem.title = NSLocalizedString(#"TabBar_news_label",nil);
editoSplitViewController.tabBarItem.image = [UIImage imageNamed:#"tabBar_news_icon.png"];
tabBarController.viewControllers = [NSArray arrayWithObjects:searchSplitViewController,favoritesSplitViewController,agencySplitViewController,editoSplitViewController,nil];
[window addSubview:[tabBarController view]];
I want to add a fifth item which will display a popover... any idea ? Thanks
To get my UITabBarItem frame I noticed that on the iPad (on iPhone items are autorisizingWidth it's more simple) items are 75px width and are spaced by 34px.
So I do :
(tabBar.frame.size.width-((75*[tabBarController.items count])+(34*[tabBarController.items count]-1)))/2
to get the first flexible sapce width.
Then I add :
(75*indexOfItemToReach)+(34*(indexOfItemToReach-1))+(75/2)
To get the width center of the item.
I would advice against this because that's not the expected behavior for a tab bar. However, you could create a UIPopoverController and display it using presentPopoverFromRect.
UIPopoverController *pop = [[UIPopoverController alloc] initWithContentViewController:someVC];
[pop presentPopoverFromRect:CGRectMake(100,100,100,100) permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
You can crawl the tab bar's view hierarchy and look for UIControl subclasses (they may come up in random order, so you'll want to sort them by which one's center.x is leftmost). Each one is a tab bar button, which will have a rect.
This approach appears to be within the realm of App Store-safe coding, particularly if you fall back to just using the tab bar's frame if an OS upgrade breaks your code.
UIView has a handy undocumented method called recursiveDescription that's incredibly useful for debugging. E.g.:
(gdb) po [[[[[UIApplication sharedApplication] delegate] tabBarController] view] recursiveDescription]

How to push a new view upon opening push notification while app is closed?

So what I'm trying to do is when you click view on receiving a push notification when the app opens it has the presented view push a new controller with details regarding the notification. I'm using a UITabBarController with UINavigationControllers. Any help would be much appreciated, I've tried searching but I couldn't seem to find anything that pointed me in the right direction. Current code below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
[application setStatusBarStyle:UIStatusBarStyleBlackOpaque];
tabBarController = [[UITabBarController alloc] init];
controller = [[controller alloc] init];
UINavigationController *controller1 = [[[UINavigationController alloc] initWithRootViewController:controller] autorelease];
controller1.tabBarItem.image = [UIImage imageNamed:#"icon_news.png"];
[controller setTitle:#"View"];
[controller release];
controller = [[controller alloc] init];
UINavigationController *controller2 = [[[UINavigationController alloc] initWithRootViewController:controller] autorelease];
controller2.tabBarItem.image = [UIImage imageNamed:#"icon_news.png"];
[controller setTitle:#"View"];
[controller release];
controller = [[controller alloc] init];
UINavigationController *controller3 = [[[UINavigationController alloc] initWithRootViewController:controller3] autorelease];
controller3.tabBarItem.image = [UIImage imageNamed:#"icon_news.png"];
[controller setTitle:#"View"];
[controller release];
controller = [[controller alloc] init];
UINavigationController *controller4 = [[[UINavigationController alloc] initWithRootViewController:controller] autorelease];
controller4.tabBarItem.image = [UIImage imageNamed:#"icon_news.png"];
[controller setTitle:#"View"];
[controller release];
controller = [[controller alloc] init];
UINavigationController *controller5 = [[[UINavigationController alloc] initWithRootViewController:controller] autorelease];
controller5.tabBarItem.image = [UIImage imageNamed:#"icon_news.png"];
[controller setTitle:#"View"];
[controller release];
tabBarController.viewControllers = [NSArray arrayWithObjects:controller1, controller2, controller3, controller4, controller5, nil];
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
launchDefault = YES;
//[self performSelector:#selector(handlePostLaunch) withObject:nil afterDelay:0];
// Push Notification info
NSDictionary *apns = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
NSString *result = [[[apns valueForKey:#"aps"] valueForKey:#"alert"] valueForKey:#"loc-args"];
NSString *playerID = [NSString stringWithFormat:#"%#", result];
playerID = [[playerID componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:#""];
playerID = [playerID stringByReplacingOccurrencesOfString:#" " withString:#""];
playerID = [playerID stringByReplacingOccurrencesOfString:#"(" withString:#""];
playerID = [playerID stringByReplacingOccurrencesOfString:#")" withString:#""];
NSLog(#"Player ID: %#", playerID);
if (![playerID isEqualToString:#"null"]) {
if (!detailViewController) {
detailViewController = [[PlayerDetailViewController alloc] init];
}
NSManagedObjectContext *moc = [[AppController sharedAppController] managedObjectContext];
NSFetchRequest *req = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Players"
inManagedObjectContext:moc];
[req setEntity:entity];
NSPredicate *pre = [NSPredicate predicateWithFormat:#"playerID=%#", playerID];
[req setPredicate:pre];
NSError *error;
NSArray *list = [moc executeFetchRequest:req error:&error];
[req release];
Players *player = [list lastObject];
[detailViewController setPlayer:player];
//Want to Push view here
[detailViewController release];
detailViewController = nil;
}
return YES;
}
If application is launched by a notification then it will be present in the application delegate's application:didFinishLaunchingWithOptions: launchOptions dictionary under the key UIApplicationLaunchOptionsRemoteNotificationKey, which has all the info the notification has (JSON converted to NSDictionary I believe).
EDIT:
Got the question wrong, I think what you're looking for is just the pointer to the currently selected navigation controller. You get that if you query [tabbarcontroller selectedViewController], which returns the visible navigation controller. Then simply push the newly created controller on top of the stack of that navigation controller.

iAd Positioning Question

I have my iAd currently displaying at the top, but I believe it will look better at the bottom. How can I modify my code to accomplish this without interface builder. Also if anyone sees any errors, please let me know. This is my first iAd attempt.
- (void)viewDidLoad {
[super viewDidLoad];
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
adView.frame = CGRectOffset(adView.frame, 0, -50);
adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifier320x50];
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifier320x50;
[self.view addSubview:adView];
adView.delegate=self;
self.bannerIsVisible=NO;
[super viewDidLoad];
NSArray *langArray = [[NSArray alloc] initWithObjects:
#"Split", #"2", #"3", #"4", #"5", #"6", #"7", #"8", #"9", #"10", nil];
self.people = langArray;
[langArray release];
NSArray *osArray = [[NSArray alloc] initWithObjects:
#"0%", #"1%", #"2%", #"3%", #"4%", #"5%", #"6%", #"7%", #"8%", #"9%",
#"10%", #"11%", #"12%", #"13%", #"14%", #"15%", #"16%", #"17%", #"18%",
#"19%", #"20%", #"21%", #"22%", #"23%", #"24%", #"25%", #"30%", #"35%",
#"40%", #"45%", #"50%", nil];
self.percent = osArray;
[osArray release];
}
I also added a banner for reference into interface builder and used that to input into the code, that does not work as well.
adView.frame = CGRectOffset(adView.frame, 0, 410);
Please take a look at the iAd implementation example code in the Apple docs. iAdSuite
Their example places the banner across the bottom. It also shows best practices like placing the banner off screen and brings on screen only once the ad is loaded. It also shows code to deal well with orientation chances.
Give this a try:
- (void)viewDidLoad {
[super viewDidLoad];
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
adView.frame = CGRectOffset(adView.frame, 0, 50);
adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifier320x50];
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifier320x50;
[self.view addSubview:adView];
adView.delegate=self;
self.bannerIsVisible=NO;
[super viewDidLoad];
NSArray *langArray = [[NSArray alloc] initWithObjects:
#"Split", #"2", #"3", #"4", #"5", #"6", #"7", #"8", #"9", #"10", nil];
self.people = langArray;
[langArray release];
NSArray *osArray = [[NSArray alloc] initWithObjects:
#"0%", #"1%", #"2%", #"3%", #"4%", #"5%", #"6%", #"7%", #"8%", #"9%",
#"10%", #"11%", #"12%", #"13%", #"14%", #"15%", #"16%", #"17%", #"18%",
#"19%", #"20%", #"21%", #"22%", #"23%", #"24%", #"25%", #"30%", #"35%",
#"40%", #"45%", #"50%", nil];
self.percent = osArray;
[osArray release];
}