I've nearly perfected my first iOS app as a single view using a storyboard in Xcode 5. Now I would like to include a tab bar with three copies of that same view. I.e. there will be three different data sets displayed in exactly the same way, selectable from the tabs.
I'm struggling with the approach to make this conversion. As I understand it all my model and controller code can remain identical (save for fetching the data unique to each) but I am lost as to whether I modify the storyboard or do it programatically.
The storyboard approach seems wrong as each view wants its own definition, when they should share the same. The code approach makes more sense but I am struggling with finding all the pieces to make it work. I've had a couple of goes and cannot get the tabbed view to even display when launched in the simulator.
I understand my existing view will need to shrink to fit but I have auto layout working, so that should take care of itself.
Just to clarify, I built the app from the "single view" template and am using the storyboard currently to launch and connect everything.
As per the comment I left above, here's the solution I went with.
Attach the existing view controller to the tab bar controller by dragging.
Remove any default added views from the tab controller, leaving only mine.
Mark the tab controller as the initial view. (And unmark my original.)
Change my original view controller to cope with the space taken by the tab bar (in my case I don't want anything under it so I unticked "Under bottom bars".)
In my code, throw away the existing single attached view and instead establish three
Inside the app delegate's didFinishLaunchingWithOptions method...
// Add extra tabs
UIViewController *vc1, *vc2, *vc3;
vc1 = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"CBViewController"];
[vc1 setTabBarItem:[[UITabBarItem alloc] initWithTitle:#"Tab A" image:[UIImage imageNamed:#"tabA_unselected"] selectedImage:[UIImage imageNamed:#"tabA_selected"]]];
vc2 = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"CBViewController"];
[vc2 setTabBarItem:[[UITabBarItem alloc] initWithTitle:#"Tab B" image:[UIImage imageNamed:#"tabB_unselected"] selectedImage:[UIImage imageNamed:#"tabB_selected"]]];
vc3 = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"CBViewController"];
[vc3 setTabBarItem:[[UITabBarItem alloc] initWithTitle:#"Tab C" image:[UIImage imageNamed:#"tabC_unselected"] selectedImage:[UIImage imageNamed:#"tabC_selected"]]];
_tabController = (UITabBarController *)self.window.rootViewController;
[_tabController setViewControllers:[NSArray arrayWithObjects:vc1, vc2, vc3, nil] animated:YES];
Hoping somebody can shed some light on this issue...
I'm working on an app that has multiple UIViewControllers each with UITableViews and UIViews in them. I wish to change the background colour for one of the UIViews programmatically. Easy enough to do. I use the RGB values for the colour from a global constants file so that every screen uses the same colour and it can be changed easily for every screen. The issue is that I presently have the code to change the background colour of the view in the viewDidLoad method and I physically see the view change colour. So it loads with whatever it's set to in interface builder and then switches to what I'm setting it to.
Obviously I just want it to appear already set to the colour I'm trying to set it to.
Any thoughts?
More Info
The UIViewController is loaded as a subview into another UIViewController. This parent UIViewController manages a few other UIViewController and allows the user to switch between them. This is how the child UIViewController is loaded:
SomeViewController *vc = [[SomeViewController alloc] initWithNibName:#"SomeViewController" bundle:nil];
self.someViewControllerOutlet = vc;
osvc = nil, [osvc release];
[self.view insertSubview:self.someViewControllerOutlet.view atIndex:0];
Hope this clarifies things.
try using
-(void)awakeFromXib
{
// do your code here
}
I have a UINavigationController with a left and a right button on an app being used as a remote control for a piece of hardware. I would like to show that the hardware is connected to the app by displaying an icon in the navigation bar to the left of the right button. From the documentation it looks as though I can only add UIBarButtonItems which make me suspect there is another, more conventional place for my 'connected LED' indicator.
So my question is can I display an icon in a UINavigationController navigation bar and if not where should I display it?
UINavigationBar is a subclass of UIView, so you can add items to it like this:
[navBar addSubview:whatever];
The navigation bar is a property of the navigation controller (i.e. you can reference it like this self.navigationController.navigationBar).
There isn't really a "conventional place" for something like this. :)
I suspect this 'connected LED' should be displayed on all views, regardless of the current view (and its UINavigationItem). If that is correct, the easiest way would probably be to NOT put that icon in the actual UINavigationBar, but place it as a separate UIView in the UINavigationBar's superview.
you should be able to just create a uiview programatically and add it as a subview of the navbar
UIImageView *connectedView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"connected-icon.png"]];
[self.navigationController.navigationBar insertSubview:connectedView atIndex:0];
[connectedView release];
if insertSubview doesn't work as you expect try addSubview:
[self.navigationController.navigationBar addSubview:connectedView];
You probably want to create the connectedView as a property though so you can (more) easily remove it when you are no longer "connected".
see this other examples of the approach
try this code
[[[yourViewController viewControllers] lastObject] navigationItem].titleView = yourImageView;
worke for me in customising navigation bar in mail controller. Hope you get some idea from here.
I have a TabBarController set as main controller tab, where names were defined using interface builder. Now I would like to change its names programmatically.
How could it be done?
Updated to XCode 8
Since my original answer, a lot has happened: Swift 3, Storyboards, etc. Title is usually the one that all views share, and can be set in the attributes inspector
Also, for more control, you can always drag the UITabBarItem, and UINavigationItem elements from the designer view. You must drag them to the view that's gonna be displayed in the tab bar/navigation controller. Basically they store the info as "I wanna be displayed in tab bar like this".
Hello Scene is getting a TabBarItem added to it, so it can be configured.
These two elements behave exactly as accessing the view controller's .tabBarItem and .navigationItem properties via code. These properties always exist in code if they are child of the corresponding object (nav has navItem, and tab has tabItem), you don't need to add them in storyboard/xib to have them.
This last thing is kinda confusing, since in the storyboard/xib it appears you're adding them to the view controller, but in truth you're just saying "the nib will configure these properties too".
Original Answer
The name that appears on the tab bar comes from the UIViewController's title property,
self.title = #"Name me!";
You can change the title at any point, and it should update the text appearing on the tab bar item. But be wary, do this as soon as possible, ideally, in the init method in use (or initWithNibName:bundle:, or initWithCoder:).
The key here, is that the init methods are called as soon as the tab bar appears on screen, as it initialises all of its view controller. If you were to do it on viewDidLoad, that would only get called if you actually select the tab, then other family of calls, same goes for awakeFromNib, viewWillAppear:, viewDidAppear:, etc.
The idea of having a title on the UIViewController, is to keep things consistent. If you show that viewController on a UINavigationController, the navigation bar on top should use the title property, as it does when using back. The UITabBarController also respects the same title property and changes accordingly.
In terms of reusability, you should be setting the title only from the inside of the UIViewController subclass.
The way of the Nib
Using nibs or storyboards? If you have a UIViewController, you can give it the name straight up in the attributes inspector (or ⌥⌘4)
Unfortunately, if the File Owner is the UIViewController subclass, then you won't be able to access it this way, simply because, XCode registers the File Owner as an "External Object", and doesn't show a configuration panel for it. :(
Multiple titles, same view controller
But sometimes, you just want to have them named differently
// Modify the display title on the tab bar
self.tabBarItem.title = #"World";
// Modify the display title on the navigation bar
self.navigationItem.title = #"Hello World";
Screwing with the neighbours
Each UIViewController should handle his own name, what if you want to force it from the outside (and thus, completely violating the original thing I said about reusability)?
// Rename the other guy's .title property
[[self.tabBarController.viewControllers objectAtIndex:<#Index#>] setTitle:#"Hello World"];
// Or do as before, and rename the other guy's tab bar
[(UITabBarItem*)[self.tabBarController.tabBar.items objectAtIndex:<#index#>] setTitle:#"Hello World"];
You could also probably do it with the navigation item, but that would require more gymnastics than I'm comfortable with.
However it is possible to do it in code, it is better to set this directly in Storyboard. How?
Just tap the appropriate tab bar item inside controller (NOT INSIDE TABBAR CONTROLLER).
Then switch to attribute inspector on the Utilities panel.
Now you are able to change everything:-)
Swift 4+
tabBarController?.tabBar.items![1].title = "xx"
In your viewController.m
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
//Here you are setting title
self.title = NSLocalizedString(#"Title", #"Title");
}
return self;
}
This is how you can change the name and the image of the icon of a tab bar:
self.tabBarItem = [[[UITabBarItem alloc] initWithTitle:#"Main Tab" image:[UIImage imageNamed:#"maintab.png"]] autorelease];
You probably want to do this in UITabBarController::viewDidLoad in which case you need to set the view controller's title because the tab bar items are currently 0 at that point.
So use
[[self.viewControllers objectAtIndex:0] setTitle: #"Buga"];
[[self.viewControllers objectAtIndex:1] setTitle: #"Nuga"];
I'm using Xcode Version 8.2.1 (8C1002) and this works for me:
I'm developing a little example for iPad from a UISplitView XCode Template. It's formed by a root controller which is shown in the left of the window and a detail view which is shown in the right.
What I want to achieve is very simple (at least I think so) but I can't find in the documentation the way to do it.
I'd like to substitute the root controller (which appears fixed in the left) with a new controller (for example as response to a event launched when you push a button). I've tried this:
ColorPicker *controlador = [[ColorPicker alloc] initWithNibName:nil bundle:nil];
[self.rootViewController presentModalViewController:controlador animated:YES];
[controlador release];
What happens with that is that the new pushed controller fills the entire window, whereas what I want is that appears fixed at the left with the two columns format that were at the beginning.
You need to set the modalPresentationStyle to an appropriate value,
controlador.modalPresentationStyle = UIModalPresentationCurrentContext;
UIModalPresentationCurrentContext instructs the view controller to appear modally within the frame of the rootViewController.
Use pushViewController:animated instead may fix this. About ModalViewController, check document http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html