Programmatically create a UIView for UITabBarController - uiview

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

Related

How to set NavigationController navigationItem title from ViewController loaded by Xib

I've a UIViewController which loads it's view form a Xib file. In my AppDelegate.m I would like to initiate my rootViewController with that myViewController and I would like that the title of the navigtionItem is set by taking the NavigationBar view which is part of the Xib file of the myViewController:
MyViewController *myViewController = [[MyViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:myViewController];
According to the documentation
Each time the top-level view controller changes, the navigation controller updates the navigation bar accordingly.
In my setup this seems not to happen or I haven't indicated that my NavigationBar view is actually the navigationBar to consider.
How can I tell the NavigationController to update it's navigationItem content (title, left and right bar buttons) according the NavigationBar view which is part of the Xib file from myViewController?
Update
My Xib layout looks like this:
I know I can set those items in code by:
self.navigationItem.titleView = ...;
self.navigationItem.leftBarButtonItem = ...;
But I want them do design in the Xib file of the ViewController and they should be used in the NavigationController.
In ViewWillAppear method in your ViewController set-
self.navigationItem.title = #"Title name";
Also in the same way you can set self.navigationItem.leftBarButton and RightBarButton items
Adding a UINavigationBar view to the main UIView doesn't do what you think it does. It merely adds a navigation bar view there in the view, it does not tie into the UINavigationController.
If you use a storyboard, you can add the UINavigationItem as a child of the UIViewController. But since you are not using a storyboard, the easiest way to do it is to update the navigationItem in viewDidLoad.
Sidenote: Apple does not recommend using viewDidLoad to setup the navigation item. If you really want to do it the proper way, you can for example do it in the navigationItem getter.
- (UINavigationItem*)navigationItem
{
// get super navigation item
UINavigationItem *navItem = [super navigationItem];
// do stuff
return navItem;
}

UIScrollView common for different viewControllers

I had to have a tabBar with 9 tabs, so I added a Srollview(MHScrollViewController) with 9 buttons instead of tabBar. On click of each button, I add a viewController as subview to the Srollview.
In AppDelegate, have the following code:
MHScrollViewController *scrollViewController = [[MHScrollViewController alloc] initWithNibName:#"MHScrollView" bundle:nil];
scrollViewController.managedObjectContext = [self managedObjectContext];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:scrollViewController];
self.window.rootViewController = self.navigationController;
Now say for one tab (button), I have added MHBikesViewController to MHScrollViewController as subView. In MHScrollViewController , I do this
bikesViewController = [[MHBikesViewController alloc] initWithNibName:#"MHBikesView" bundle:nil];
bikesViewController.managedObjectContext = self.managedObjectContext;
bikesViewController.view.frame = baseViewiPhone.frame;
CGRect theFrame = bikesViewController.view.frame;
theFrame.origin.y = 0;
bikesViewController.view.frame = theFrame;
bikesViewController.navigationController = self.navigationController;
[baseViewiPhone addSubview:bikesViewController.view];
Now, I have two buttons on the MHBikesViewController page. When clicked, I want to push a new viewcontroller on MHBikesViewController. I am able to push, but the scrollView gets hidden under this viewcontroller.
UINavigationController will cover all its contents with newly pushed controller anyway, so you need to take your scrollview with buttons outside of navigationcontroller.
Beware of UIViewController parent/child relationships & responsabilities when designing UI.
A controller holds a main UIView, and all its subviews.
When adding this viewController's view into a more complex view hierarchy, this controller should then be the child of the viewController controlling this 'containement' UI.
Ask yourself : what IS your model for containment ?
9 tabs and some related content that occupy the rest of the screen?
Then in your case, MHScrollViewController is the daddy, it holds scrollable tabs and current viewController main view. It shouldn't be UINavigationController (which can be himself parent 'content' holding your MHBikesViewController)
Parent->Child containement in your case:
MHScrollViewController -> UINavigationController -> MHBikesViewController
Adding and removing child viewController is responsibility of the parent.
//(somewhere in MHScrollViewController.m or .h )
#property (nonatomic, strong) UIViewController *newContentController;
#property (nonatomic, weak) UIScrollView *tabsScrollView;
// method for pushing any 'tab' controller
// might be your UINavigationController
- (void)displayTabController:(UIViewController *)vc
{
// remove previous controller
if (self.contentController) {
[self.contentController.view removeFromSuperview];
[self.contentController removeFromParentViewController];
}
//push the new controller, maintaining child/parent relationship
self.contentController = newContentController;
[self.view addSubview:contentController.view];
[self.contentController didMoveToParentViewController:self];
// set frame of contentController so that it stays above scrollView
self.contentController.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height - self.tabsScrollView.bounds.size.height)
}
You can have a tab bar with 9 tabs the standard way. It will automatically create a "more" tab. It might not be as slick as you wanted.

UITabBarController offsetting content at first sight

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.

How to use UISplitViewController

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.

Set UITabBarItem title programmatically?

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

Resources