Programmatically setting UITabBarItem icons with StoryBoards? - iphone

I want to use a UITabBarSystemItem for the icon of one of my tabBarItem's but I'm using storyboards. I'm not sure where to set it. If I set it in the view's viewDidLoad then it doesn't change until you push the button in the tabBar. Before that it's just the blue ? square.
And as far as I know, you can't use UITabBarSystemItems in IB inspector.
UPDATE:
Well first of all I'm an idiot. You can totally choose the icon in the IB Inspector.
Tab Bar Item -> Identifier -> Choose your icon.
But the question still remains how to do it programmatically. Or rather when/where?

When using storyboards, a view controller initializes using the initWithCoder constructor so you could override that function and set the system item icon there like so
- (id)initWithCoder:(NSCoder*)aDecoder
{
if(self = [super initWithCoder:aDecoder])
{
self.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFavorites tag:1];
}
return self;
}
Naturally, you can change the value of the system item to any of the values supported. Apple lists them here

Check this code for your problem: Its working in my app.
- (NSArray *) initializeViewControllers
{
NSArray *viewControllerArray = nil;
viewController1 = <View Init Code>
viewController2 = <View Init Code>
viewController3 = <View Init Code>
1stNavController = [[UINavigationController alloc] initWithRootViewController:viewController1];
UIImage *img = [UIImage imageNamed:#"tab_home"];
[1stNavController .tabBarItem initWithTitle:#"Home" image:img tag:1];
2ndNavController = [[UINavigationController alloc] initWithRootViewController:viewController2];
img = [UIImage imageNamed:#"tab_timeDrop"];
[2ndNavController .tabBarItem initWithTitle:#"Time Entry" image:img tag:2];
3rdNavController = [[UINavigationController alloc] initWithRootViewController:viewController3];
img = [UIImage imageNamed:#"tab_invoiceSummary"];
[3rdNavController.tabBarItem initWithTitle:#"Invoice Summary" image:img tag:3];
viewControllerArray = [NSArray arrayWithObjects:1stNavController,2ndEntryNavController,3rdReportNavController, nil];
return viewControllerArray;
}
This code is returning View Controllers with Images for their respective tabs. Here i used Navigation Controller inside the tabbar controller. you can also use view controller instead of navigation Controller.
Just add this code and initialize your tabbar controller as follows inside appdidfinishlaunching method:
tabbarController = [[UITabBarController alloc] init];
_tabbarController.viewControllers = [self initializeViewControllers];
self.window.rootViewController = tabbarController;
Hope it works.
Please reply.

Well that's quite simple!
For the where -> create a custom TabBarController (e.g. WBTabBarController).
In your StoryBoard explicitly set it.
For the how -> just overwrite viewDidLoad of the WBTabBarController and set your images for the TabBarItems. In the following example this was done using the NIKFontAwesomeIconFactory:
#import "WBTabBarController.h"
#import "NIKFontAwesomeIcon.h"
#import "NIKFontAwesomeIconFactory.h"
#import "NIKFontAwesomeIconFactory+iOS.h"
#interface WBTabBarController ()
#end
#implementation WBTabBarController
- (void)viewDidLoad
{
[super viewDidLoad];
NIKFontAwesomeIconFactory *factory = [NIKFontAwesomeIconFactory tabBarItemIconFactory];
UITabBarItem *item0 = self.tabBar.items[0];
item0.image = [factory createImageForIcon:NIKFontAwesomeIconApple];
UITabBarItem *item1 = self.tabBar.items[1];
item1.image = [factory createImageForIcon:NIKFontAwesomeIconStackOverflow];
}
#end

Assuming the initial scene of your storyboard is the tab bar view controller, you can access it in applicationDidFinishLaunching, it is the rootViewController of the app delegate's window. I don't know if you can swap in a system item if the bar item is already present, but you can definitely set the image and title.

Related

Passing data between ViewController and TabBar children

I am developing an application which has a a TableView. When I press any cell the app goes to the next ViewController. In this viewController I have created a TabBarController by code which has 3 children ViewControllers. So, I want to pass a variable from the TableView to the Children of the TabBar. I can pass the variable to the TabBar, I have watched it with the NSlog function. It is really weird for me that in the children ViewControllers I also have type a NSlog and the variable is null, but in the output I see first this.
2013-10-01 03:01:40.687 Prototype[38131:c07] proId (null) // This is the children log from vc2 ViewController "YPProjectViewController"
2013-10-01 03:01:40.697 Prototype[38131:c07] projectID 433 // This is the TabBar LOG YPTabBarViewController
Does somebody know why I can first the Children NSLog? Maybe there is the solution.
#import "YPTabBarViewController.h"
#import "YPProjectViewController.h"
#import "YPCommentsViewController.h"
#import "YPProposalsViewController.h"
#interface YPTabBarViewController ()
#property (nonatomic,strong)UITabBarController *tabBar;
#end
#implementation YPTabBarViewController
#synthesize tabBar;
#synthesize projectId = _projectId;
- (void)viewDidLoad
{
[super viewDidLoad];
[self setUpTabBar];
}
// Set up tabBar
-(void)setUpTabBar
{
YPCommentsViewController *vc1 = [[YPCommentsViewController alloc] init];
vc1.title = #"Comments";
vc1.view.backgroundColor = [UIColor clearColor];
UINavigationController *contentNavigationController = [[UINavigationController alloc] initWithRootViewController:vc1];
YPProjectViewController *vc2 = [[YPProjectViewController alloc] init];
vc2.title = #"Project";
vc2.view.backgroundColor = [UIColor clearColor];
vc2.proId = _projectId;
NSLog(#"PROJECT ID %#", vc2.proId);
// UINavigationController *contentNavigationController2 = [[UINavigationController alloc] initWithRootViewController:vc2];
YPProposalsViewController *vc3 = [[YPProposalsViewController alloc] init];
vc3.title = #"Proposal";
vc3.view.backgroundColor = [UIColor clearColor];
UINavigationController *contentNavigationController3 = [[UINavigationController alloc] initWithRootViewController:vc3];
tabBar = [[UITabBarController alloc] init];
tabBar.viewControllers = #[contentNavigationController,vc2,contentNavigationController3];
tabBar.selectedIndex = 1;
[tabBar.view setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
[tabBar willMoveToParentViewController:self];
[self addChildViewController:tabBar];
[tabBar didMoveToParentViewController:self];
[self.view addSubview:tabBar.view];
}
In terms of understanding the problem, your NSLog statement in the "tab bar controller" is logging the value of vc2.proID immediately after setting it. But your NSLog output show us that that second tab's view controller is logging its results before that. That's why it's nil when the second tab's view controller's viewDidLoad logs it, because that log is happening before the tab bar controller had a chance to set the value and log it itself.
So, there are a couple of ways you could fix this:
Right before your assignment of vc2.proId, you have an innocuous line of code that says:
vc2.view.backgroundColor = [UIColor clearColor];
That line of code triggers the second view controller's view to be loaded (and its viewDidLoad will be called). If you move the assignment of vc2.proId to before you start accessing any of vc2's views, that will change the order that your NSLog statements appear (or, much better, move the setting of the background color into viewDidLoad of the child controllers).
You could just create your own init method that accepts the project id as a parameter. That would also ensure that it's set before viewDidLoad. Thus, YPProjectViewController could have a method such as:
- (id)initWithProjectId:(NSString *)projectId
{
self = [self init];
if (self)
{
_proId = projectId;
}
return self;
}
Two unrelated observations regarding the custom container calls:
When you call addChildViewController, it calls willMoveToParentViewController for you. So you should remove the call to willMoveToParentViewController. See the documentation for that method.
You might even want to retire these custom container calls altogether, and just make YPTabBarViewController a subclass of UITabBarController, itself, rather than UIViewController. That eliminates the need to custom container calls altogether. Clearly, if you have other needs for the custom container, then feel free, but it's redundant in this code sample.

Populate Table With Help of PopOverController - Objective C

I am using a UIButton, on clicking it I want to display the contents that are present in my NSMutableArray in UITableView with the help of UIPopOverController i.e. I want a UITableView to pop up whose cells show the contents of my NSMutableArray.
I am using the following lines of code:
UITableViewController *table= [[UITableViewController alloc]init];
table.delegate = self;
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:table];
self.popoverController = popover;
popoverController.delegate = self;
NSString *hDir = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *hFilePath = [hisDir stringByAppendingPathComponent:#"hhhh.txt"];
NSArray *array = [NSArray arrayWithContentsOfFile:hFilePath ];
NSMutableArray *kkkk = [[NSMutableArray alloc] init];
for (NSDictionary *dict in array) {
[kkkk addObjectsFromArray:[dict allKeys]];
}
table = [[UIImageView alloc] initWithFrame:[window bounds]];
// Set up the image view and add it to the view but make it hidden
[window addSubview:table];
table.hidden = YES;
[window makeKeyAndVisible];
I am unable to get the UITableView to pop up on the press of my UIButton. Can anyone help me to sort it out?
One way to show the UITableView in the UIPopOverController is by creating a new UIViewController class. And invoking it in initWithContentViewController method of UIPopOverController.
1. Create a new UIViewController or UITableViewController class. Create an instance of it.
2. Use the instance in the initWithContentViewController method of UIPopOverController.
3. Mention from where it should "pop"
For Example in your Button action :
-(IBAction)yourButtonAction:(id)sender
{
YourNewViewController*newVC=[[YourNewViewController alloc]init];
UIPopoverController*somePopOver=[[UIPopoverController alloc]initWithContentViewController:catergoryVC]; //Tell which view controller should be shown
[somePopOver setPopoverContentSize:CGSizeMake(200, 200)]; // set content size of popover
[somePopOver presentPopoverFromRect:yourButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES]; //From where it should "pop"
}
It seems you want to present it from a UIBarButtonItem so instead of presentPopoverFromRect use presentPopoverFromBarButtonItem
[somePopOver presentPopoverFromBarButtonItem:yourBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
If you want to display popover on press of button click, then first add your button in viewcontroller, display that view controller as follows:
In app delegate write code:
MyViewController *viewController = [[MyViewController alloc] init];
[self.window addSubView:viewController.view];
In MyViewController add button and provide target to that button displayPopup as follows:
-(void)displayPopup:(id)sender
{
UITableViewController *tblViewPopover = [[UITableViewController alloc] init];
tblViewPopover.tableView.delegate = self;
tblViewPopover.tableView.dataSource = self;
tblViewPopover.tableView.backgroundColor = [UIColor whiteColor];
tblViewPopover.tableView.separatorStyle= UITableViewCellSeparatorStyleSingleLine;
float theWidth = 280;
tblViewPopover.contentSizeForViewInPopover = CGSizeMake(theWidth,200);
if(m_popOvrController){
[m_popOvrController dismissPopoverAnimated:NO];
[m_popOvrController release];
m_popOvrController=nil;
}
m_popOvrController = [[UIPopoverController alloc] initWithContentViewController:tblViewPopover];
[tblViewPopover release];
[m_popOvrController presentPopoverFromRect:sender.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
}
and you can use tableview delegate methods to display data in tableview.
I think, UIPopoverViewController is initialized using UIViewController and here you are using UIView(UITableView).
Can you please try using UITableViewController instead?
Also, if things does not work according to plan when you create it using the code try using an XIB explicitely.
This should help.

How can I place a header image fixed at the top of my Tab Application?

I want to create a Tab Application with a header image that is always present, no matter what Tab Item is active.
The example would be Foursquare:
I want to be able to place buttons and have different information displayed on that header.
Is that a simple Navigation Bar or something else?
Usually, for each tab is associated a viewController. You can notice it in the boilerplate which xcode creates when you choose "Tabbed Application".
Then, in each viewDidLoad or in the init of each viewcontroller you can set:
self.navigationItem.titleView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image.png"]];
Then just change self.navigationItem.leftBarButtonItem and self.navigationItem.rightBarButtonItem with your controls on each viewController.
Edit:
In the appDelegate (in the didFinishLaunchingWithOptions method) you've to set something like this if you want use the navigationcontrollers:
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
UINavigationController *myNav1=[[UINavigationController alloc] initWithRootViewController:viewController1];
UINavigationController *myNav2=[[UINavigationController alloc] initWithRootViewController:viewController2];
UIImage *navBackgroundImg = [UIImage imageNamed:#"bg_navBar.png"];
UIImage *tabBackgroundImg = [UIImage imageNamed:#"bg_tabBar.png"];
[myNav1.navigationBar setBackgroundImage:navBackgroundImg forBarMetrics:UIBarMetricsDefault];//iOS 5 only
[myNav2.navigationBar setBackgroundImage:navBackgroundImg forBarMetrics:UIBarMetricsDefault];//iOS 5 only
[[UITabBar appearance] setBackgroundImage:tabBackgroundImg];//iOS 5 only
self.tabBarController.viewControllers = [NSArray arrayWithObjects:myNav1, myNav2, nil];
self.window.rootViewController = self.tabBarController;
Looks like a simple navigation bar, but they aren't exactly simple. You need to place/create a NavigationItem on the bar (after placing/creating the bar itself) and then set the titleView to a custom view with your image. According to the documentation the left bar button (close in your first screen) has to be nil or else the titleView is ignored. Though you can place buttons in this custom view for left buttons.
I found out the easiest thing to do is to write:
- (void)viewDidLoad
{
[[UINavigationBar appearance] setBackgroundImage:
[UIImage imageNamed:#"UINavigationBar.png"] forBarMetrics:UIBarMetricsDefault];
}
At my MainViewController, and all Navigation bars that get created on each view controller gets configured like that.

Three20 & TabBarController

I'm stuck on something.
I'm using three20 and the TTTNavigator example. Where I can find a TabBarController that is using :
[self setTabURLs:[NSArray arrayWithObjects:#"tt://crush",
#"tt://crushes",
nil]];
to create each tab.
Ok until here all is ok, my problem is that I have all my tabs without title and image. I know how to set individual when it loads the view controller inside - (void)viewDidLoad :
self.title = #"crush";
UIImage* image = [UIImage imageNamed:self.title];
self.tabBarItem = [[[UITabBarItem alloc] initWithTitle:self.title image:image tag:0] autorelease];
but this is a problem because when you init the app all the tabs except the selected are empty.
Any suggest on how to implement that.
Ok I've resolved, I used the -init method of each view controller.. like usually... but what I need to change was :
[self setTabURLs:[NSArray arrayWithObjects:#"tt://crush/1",
#"tt://crushes/2",
nil]];
And in the map :
[map from:#"tt://crush/(init)" toViewController:[MakeCrushViewController class]];
[map from:#"tt://crushes/(init)" toViewController:[MyCrushesViewController class]];
for me right now it looks pretty weird.. but ok is working, don't ask me why you need to set 1 and 2 before the links.. if I set 1 on each it crashes...
This guy had an answer to this question in this blog post.1
Basically, within your tab view controller, just access the your view controllers
like you would without three20. In your tab view controller implimentation file
-(void)viewDidLoad{
[super viewDidLoad];
NSArray *tabs = [self viewControllers];
UIViewController *home = [tabs objectAtIndex:0];
home.tabBarItem.image = [UIImage imageNamed:#"redo.png"];
UIViewController *activities = [tabs objectAtIndex:1];
activities.tabBarItem.image = [UIImage imageNamed:#"restart.png"];
UIViewController *map = [tabs objectAtIndex:2];
map.tabBarItem.image = [UIImage imageNamed:#"lock.png"];
}

iPhone -- adding a button to a navigation bar created when the user selects a tab in the moreNavigationController

My tab bar has ten tabs. Six of these are therefore shoved into the "More" tab. Several of them do not have UINavigationControllers. I.e, the tab is controlled by a UIViewController subclass that is not a navigation controller.
When the user selects one of these, the appropriate view controller come sup, with a UINavigationBar at the top.
I want to add a button to that navigation bar. How can I do that?
Thanks.
Well, if you want to do this programmatically, then I would suggest replacing each of your viewControllers in your UITabBar with UINavigationControllers that house the respective view controllers.
So, your old code looks something like this:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UITabBarController *tbc = [[[UITabBarController alloc]init]autorelease];
[window addSubview:tbc.view];
UIViewController *mapVC = [[[UIViewController alloc] init]autorelease];
NSArray *tabViewControllerArray = [NSArray arrayWithObjects:self.mapVC, nil];
tbc.viewControllers = tabViewControllerArray;
}
New code should be:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UITabBarController *tbc = [[[UITabBarController alloc]init]autorelease];
[window addSubview:tbc.view];
UIViewController *mapVC = [[[UIViewController alloc] init]autorelease];
// add the viewController to a UINavigationController
UINavigationController *mapNav = [[[UINavigationController alloc] initWithRootViewController:mapVC]autorelease];
// put the nav controller in the array instead
NSArray *tabViewControllerArray = [NSArray arrayWithObjects:mapNav, nil];
tbc.viewControllers = tabViewControllerArray;
// this code adds a right button to the mapBav navigationBar
// this uses a custom view, but you could use a standard UIBarButtonItem too
NSArray *items = [NSArray arrayWithObjects: [UIImage imageNamed:#"flag-icon.png"], nil];
UISegmentedControl *tableControl = [[[UISegmentedControl alloc] initWithItems:items]autorelease];
tableControl.segmentedControlStyle = UISegmentedControlStyleBar;
UIBarButtonItem *segmentBarItem = [[[UIBarButtonItem alloc] initWithCustomView:tableControl] autorelease];
self.navigationItem.rightBarButtonItem = segmentBarItem;
}
There are two ways to go about it.
Just use a UINavigationController for each tab, with your view controller in it. But it sounds like you don't want to do this, so:
Put a UINavigationBar in using Interface Builder. nav bar http://cl.ly/395fb8c0a9e9df781897/content
You can then drag in UIBarButtonItems and configure them to your liking, also in IB. buttons http://cl.ly/7501d3e8e5d57dac5e00/content