I'm having trouble with my UITabBarController in the sense that my first view of the first UIViewController is being offset about 20 pixels to the bottom. Whenever I tab around and/or return to the first view controller (same instance, not released), it's fine. It's only the first encounter.
My steps:
I am allocating and initializing a UITabBarController
I am allocating and initializing 3 instances of UIViewController
I am setting the viewControllers property to an array of the above mentioned 3 items
My code:
- (void)viewDidLoad {
[super viewDidLoad];
// Allocate and initialize view controllers
self.debtsViewController = [[DebtsViewController alloc] init];
self.debtsViewController.title = NSLocalizedString(#"Debts", nil);
self.debtsViewController.tabBarController = self;
self.conclusionsViewController = [[ConclusionsViewController alloc] init];
self.conclusionsViewController.title = NSLocalizedString(#"Entries", nil);
self.conclusionsViewController.tabBarController = self;
self.settingsViewController = [[SettingsViewController alloc] init];
self.settingsViewController.title = NSLocalizedString(#"Settings", nil);
// Assign to tabBarController
self.viewControllers = [NSArray arrayWithObjects:self.debtsViewController, self.conclusionsViewController, self.settingsViewController, nil];
}
Any ideas?
Screenshot: http://cl.ly/image/2E0S001d0Q2x (notice the black space just above the UITableViewController)
i solved this problem.
```
[tab setSelectedIndex:1];
[tab setSelectedIndex:0];
```
you can manually reset the offset by switch the tab bar after the tabbarcontroller initialized
Having a glance at your screenshot made me think, that actually you should have 3 UINavigationControllers inside the UITabBarViewController. Their navigationBars will be(almost) lookalike, but it will be 3 separate instances. What does 'Settings' have in common with 'Debts'? Why would they share same navigation?
The point of using UITabBarViewController is to have independent sections of the app. I strongly recommend you Apple's guide.
Related
I have an app that communicates with an outside entities. I need to either show or hide an item on the tab bar if that entity has a switch flipped on or off.
It has to be dynamic in case the user changes from entity A to entity B and those have different settings. Tab bar item needs to show/hide if they switch and settings differ.
I used to add an item to a UITabBarController like this:
UIViewController *vc1 = [[MyViewController1 alloc] init];
[self.tabBarController addChildViewController:vc1];
UIViewController *vc2 = [[MyViewController2 alloc] init];
[self.tabBarController addChildViewController:vc2];
And I could remove items from a tab bar like this:
NSMutableArray *tbViewControllers = [NSMutableArray arrayWithArray:[self.tabBarController viewControllers]];
[tbViewControllers removeObjectAtIndex:4];
[tbViewControllers removeObjectAtIndex:4];
[self.tabBarController setViewControllers:tbViewControllers];
In my ViewController Code I had something like this:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
//get the tab bar item
UITabBarItem *tbi = [self tabBarItem];
//give it a label
[tbi setTitle:#"Tab Item"];
//create a UIImage from a file
UIImage *i = [UIImage imageNamed:#"image.png"];
//put that image on the tab bar item
[tbi setImage:i];
}
return self;
}
Now, with the advent of adaptive app layout and segues it seems that adding an item dynamically does not work. At least for me.
I get a black screen instead of the view I expect to see when doing the above. The UIView in question is basically a UIWebView with a couple custom buttons above it.
My app is fully adaptive layout compatible with UIStackViews and whatnot.
All the posts I see here referencing adding or removing items from UITabBars are all several years old, before modern adaptive layout.
Is it still possible to add/remove tab items from the tab bar anymore? Is it advisable to do so or is this now bad practice?
Any other ideas to accomplish this same goal of having an item on a tab bar or not depending on an outside setting?
Cheers,
TJ
I found my own solution and am sharing it to help others.
The trick was how the UIViewController was created.
The new way to do this is to create the view controller by instantiating from the storyboard.
I found the idea from this question.
Creating and adding to the TabView is done like this:
// Get a reference to the Tab View Controllers array
NSMutableArray *tbViewControllers = [NSMutableArray arrayWithArray:[self.tabBarController viewControllers]];
// Get a reference to the storyboard
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:[NSBundle mainBundle]];
// Instantiate a new instance of the ViewController
UIViewController *vc1 = [sb instantiateViewControllerWithIdentifier:#"MyVC"];
// Add the new view controller to the array at the desired location
[tbViewControllers insertObject:vc1 atIndex:tbViewControllers.count-1];
// Set the tab bar controllers to the newly augmented array
[self.tabBarController setViewControllers:tbViewControllers];
That's it. The view controller works as I expect it to. No more black screen.
Hope this helps someone else.
I'm trying to use a split view controller to show a navigation controller on the left and a table view on the right. I use this code in RootViewController's viewDidLoad:
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
Settings *settings = [[Settings alloc] init]; //Table view
MainView *main = [[MainView alloc] init]; //Table view
UINavigationController *nav_con = [[UINavigationController alloc] init];
NSArray *controllers = [[NSArray alloc] initWithObjects:settings, detailViewController, nil];
[nav_con pushViewController:settings animated:NO];
self.view = nav_con.view;
detailViewController.view = main.view;
I've tried like a million different ways of coding this, and this one comes the closest to correct. It displays the navigation controller in the left pane and the main view in the right. HOWEVER, in the left pane, at the top, there are two bars with a big black space between them. One of the bars in my nav controller's bar. How can I just replace the content of the left pane entirely with my navigation controller's view?
Settings and MainView better be subclasses of UITableViewController
the first object in controllers should be nav_con, not settings
delete the last two "view" lines,
and RootViewController should be a subclass of UISplitViewController and the instance that's being created should be set to window.rootViewController somewhere.
Also, it's fairly standard to do all this code external to viewDidLoad - makes me wonder what's being loaded as the view! Much easier to do all this in a nib file.
My app is based on a tab bar architecture. In order to have an easy internationalisation mechanic, I do not write any string in XIB files. viewdidload permits to change programmaticaly the strings in the views.
When my app launches, I can see the 4 tabs. But in fact only the first one loads its view controller. The others wait for user click to be loaded.
Tabs title can be changed using [self setTitle:#"Mouhahaha"]; in viewDidLoad of loaded view controller.
If I want to keep my internationalisation mechanic available, I do not set in my XIB the name of tabbar items. But, as at start all tab' view controllers are not loaded, I have blank titles for some tabs. The right title is set only when the user click on the tab.
I am looking for a way to set this title programaticaly for each tabbaritem. Do you have hints ?
Thanks a lot.
kheraud
my preferred method of doing this programmatically together with the storyboard is to make a subclass of UITabBarController, have my tab bar controller scene in my storyboard use the new subclass (with 3 UIViewController relationships from the tab bar controller to the desired view controller in the case below), and then override viewWillAppear:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSArray* titleKeys = [NSArray arrayWithObjects:#"top places",
#"localizablekey1",
#"localizablekey2",
#"localizablekey3",
nil];
[super viewWillAppear:animated];
int count = 0; for (UIViewController* viewController in self.viewControllers)
viewController.tabBarItem.title = NSLocalizedString([titleKeys objectAtIndex:count++], nil);
}
All you need to do is make an instance of UITabBarController, then alloc any views you want in it, then set the UITabBarController views. Make sure that your TabBarController is the one that is visible. Also make sure that any viewControllers you want in your tab bar are being imported with #import.
UITabBarController *c = [self tabBarController];
SecondViewController *s = [[SecondViewController alloc] init];
[s setTitle:#"Whatever"];
c.viewControllers = [NSArray arrayWithObjects:self, s, nil];
[s release];
Put this in the viewDidLoad method of the first controller allocated.
Alternatively you could just change the way your ApplicationDelegate sets up the TabBarController, but i won't go into that.
Hope this helps
Hi i have a UITabBarController with 5 tabBar items.
The forth is UIScrollView.
The area that presented by the forth tab i wont to have specific height.
so till here i've done this
This is were i create my UITabBarController.(aViewController.h)
#interface aViewController: UIViewController <UITabBarControllerDelegate>{
UITabBarController *newTabBarController;
UIView *myView;
}
aViewController.m
- (void) viewDidLoad{
newTabBarController = [[UITabBarController alloc]init];
newTabBarController.delegate = self;
myView = [[UIView alloc]initWithFrame:CGRectMake(0,0,320,self.view.frame.size.height - newTabBarController.tabBar.frame.size.height)];
NSArray *controllers = [NSArray arrayWithObjects:myView, nil];
newTabBarController.viewControllers = controllers; //this is the line that a get an error :Tread1:Program receive signal: SIGABRT
[myView release];
}
if i make a viewController subclass of UIViewController with Xcode and put it in the NSArray there is no problem but i want my view has screen.height - tabbar.height so i tryed make one programmatically.
Any help apresiated!
List item
UIView size
You can do this via Interface Builder.
Create the View you want for a given tab. Then go into the Attribute Inspector. The tab named "simulated metric" allow you to setup a TabBar (and even a NavigationBar).
SIGABRT
myView = [[UIView alloc]initWithFrame:CGRectMake(0,0,320,self.view.frame.size.height - newTabBarController.tabBar.frame.size.height)];
NSArray *controllers = [NSArray arrayWithObjects:myView, nil];
newTabBarController.viewControllers = controllers; //this is the line that a get an error :Tread1:Program receive signal: SIGABRT
This property is called viewControllers, not views.
The NSArray must contain UIViewController instances, or subclasses.
Thus, it better to define your View with IB (and configure look and feel to display TabBar, etc).
Then create your UIViewController with the method initWithNibName:bundle:, and put these instance into the newTabBarController.viewControllers.
Hope it helps
I'm looking to find out how to switch to a UISplitView from another view. The user will click on a button and the Split View should open. I'm having no luck at all.
I start with a normal view and when the user clicks on the button i try to switch to the split view by removing the current view and initing the split view controller. I would just use a nib to load it but split views don't have nib files.
Is there anyone that can get me the simplest way to do this.
You have to create the UISplitViewController programatically. You have to give it an array of two UIViewController objects (these can be from nib files). Then when you want to load the split view you send the message [window addSubView:splitViewController.view]
i have practically done something like this.
i declared a SplitViewController in viewDidLoad at one of my viewcontroller (FrameViewController)
Then i added the splitViewController that i have just declared into AppDelegate's window variable. (i have tried declaring another UIWindow variable and add SplitViewController's view to it, it will throw wait_fences: failed to receive reply: 10004003 when u change orientation)
then, set your viewController's view to hidden so that the SplitViewController will be displayed correctly..
Voila~
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (iPadProject2AppDelegate *)[[UIApplication sharedApplication] delegate];
ContentViewController* secondVC = [[ContentViewController alloc]
initWithNibName:#"ContentView" bundle:nil];
MenuViewController* firstVC = [[MenuViewController alloc]
initWithNibName:#"MenuView"
bundle:nil
withContentViewController:secondVC];
UISplitViewController* splitVC = [[UISplitViewController alloc] init];
splitVC.viewControllers = [NSArray arrayWithObjects:firstVC, secondVC, nil];
[appDelegate.window addSubview:splitVC.view];
[self.view setHidden:YES];}
BTW,
you should add these code into Yit Ming's code:
[[self view] removeFromSuperview];
Or the Split View will not work while you change the orientation.