Previously when setting up controllers programatically I have always set the size and position of the root UIView element (i.e.)
// UIViewController -loadView
CGRect viewFrame = CGRectMake(0, 20, 320, 460);
UIView *view = [[UIView alloc] initWithFrame:viewFrame];
[self setView:view];
[view release];
I have just noticed (and I wonder if anyone can confirm) that if your adding the root UIView to a controller that you don't need to set the size or position as it autosizes to the space available. (i.e.)
// UIViewController -loadView
UIView *view = [[UIView alloc] init];
[self setView:view];
[view release];
I understand that subsequent UIViews (i.e. UIButton, UILabel etc.) will need to be positioned and sized, I just want to make sure I am understanding the behaviour I am currently seeing.
It does resize the frame of the view.
UIView *view1 = [[UIView alloc] init];
NSLog(#"ViewFrame before set:%#",NSStringFromCGRect(view1.frame));
[self setView:view1];
NSLog(#"ViewFrame after set:%#",NSStringFromCGRect(view1.frame));
[view1 release];
But I could not find anything in docs that justify this.
Size of the root view of any UIViewController is managed by that controller's parent instance, that may be another controller or window. It determines the size automatically. For example, if you are creating UITabBarController, it determines sizes of all its child controllers' root views. Or, if you write your own container view controller it must determine sizes of root views of its child controllers.
See "View Management" section in this topic:
UIViewController Class Reference
Related
UIView *view =[[UIView alloc] initWithFrame:CGRect(0,0,300,70)]; //--(View created)
someViewController *someViewControllerObject = [..]; //View Controller Object created.
[view addSubview:[someViewControllerObject.view]];
I want to fit the view controller's view in the UIView's object. The above code doesn't work correctly. Can you help me figure this out?
The simplest would be to just set the frame of the controller view to the bounds of the outer view;
UIView *view =[[UIView alloc] initWithFrame:CGRect(0,0,300,70)]; //--(View created)
someViewController *someViewControllerObject = [..]; //View Controller Object created.
someViewController.view.frame = view.bounds;
[view addSubview:[someViewControllerObject.view]];
#david's answer is correct to set the initial frame of the view controller's view. set the autoResizingMask to get the behavior you want when the superview changes.
someViewControllerObject.view.frame = view.bounds;
someViewControllerObject.view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[view addSubview:someViewControllerObject.view];
This code will make it the same size as your current view.
someViewControllerObject.view.frame = view.bounds;
[view addSubview:[someViewControllerObject.view]];
I've always used IB but am trying to do everything through code and I'm failing at this task.
I have a ViewController to handle User Inputs and 2 UIViews which will both be visible at the same time(each in a separate header/implementation UIView file):
1 UIView represents a custom tab bar that changes (bottom 50 px)
1 UIView represents the displayed interface (everything above the tab bar)
Each needs to exist within its own frame, initialized from the ViewController so it can control them and what they display.
Bra, UIViewControllers have only one UIView as part of their guts.
That is, "view" ... i.e. ... the actual property view, as in self.view = something or view.hidden = YES.
However you can, of course, add as many subviews as you like to that view.
This is how views are used normally. Almost every .view has subviews inside it.
UIView *bottomThing = [[UIView alloc] init];
bottomThing.frame = CGRectMake whatever
UIView *otherThing = [[UIView alloc] init];
otherThing.frame = CGRectMake whatever
[view addSubview:bottomThing];
[view addSubview:otherThing];
In the example, we added two subviews to our main "built-in" view, which you refer to as simply "view". So we added bottomView to our "view" and we added topView to our "view."
The subviews you add could be either plain old UIView, or, your own special subclass of UIView.
MySpecialView *bottomThing = [[UIView alloc] init];
bottomThing.frame = CGRectMake whatever
ExtraordinaryView *otherThing = [[UIView alloc] init];
otherThing.frame = CGRectMake whatever
[view addSubview:bottomThing];
[view addSubview:otherThing];
(I guess FTR conceivably you could subclass UIViewController to have more than one view inside it, but that's completely pointless and irrelevant to this question.)
From your UIViewController you can manipulate the subviews in any way you want.
For example [bottomThing doStuff:3.7], bottomThing.hidden=YES, etc etc.
Once again it is absolutely normal to add more subviews inside your main "view" - this is the basic way in which iPhone apps are made. There is only one ".view" - you add more views inside it as you wish. Hope It Helps.
UIView *myView = [[UIView alloc] init];
[self.view addSubview:myView];
[myView release];
I have a UITableView which is not being resized properly using autoresizeMask (in iPhone 3.0).
The UITableView is inside a UIViewController inside a UINavigationController inside a UITabBarController, all of which are being created programatically. The status bar is visible.
The code of the UIViewController is basically:
- (void)loadView {
UIView* rootView = [[UIView alloc] init];
self.view = rootView;
[rootView release];
}
- (void)viewDidLoad {
[super viewDidLoad];
// table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 480-20-49-44)];
table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)]; table.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[self.view addSubview:table];
}
When created like this, the UITableView is slightly bigger than the available space. If I'm not mistaken, it's exactly 44 pixels bigger, the size of the navigation bar.
However, if I uncomment the commented line and comment the next line the size of the UITableView is exactly right. I would prefer to use autoresizingMask instead of manually calculating the size of the UITableView. What am I doing wrong?
Thank you in advance!
The problem seems to be that I wasn't setting the frame of the root view in loadView. If you define such frame, and then define the frame of the subviews in relation to that frame, then the autoresize masks will correctly resize the subviews according to how the root view was resized by the framework.
For example:
- (void)loadView {
UIView* rootView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
self.view = rootView;
[rootView release];
}
- (void)viewDidLoad {
[super viewDidLoad];
table = [[UITableView alloc] initWithFrame:self.view.frame];
table.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[self.view addSubview:table];
}
Thanks to Colin Gislason who pointed me in the right direction.
The autoresizing mask will not help you with the initial size of the table view. The table view is created with the frame that you give it. The autoresizing mask defines the rules for resizing this frame relative to the parent view when the parent's frame changes.
So if I define a table that is 320x100 it will stay that size unless I change it explicitly or the parent view's frame changes.
Depending on the other views, you could do the calculation based on the other views held by the parent or by the parent's frame itself.
Create UIViewController subclass instand of UITableViewController Subclass.
insert UITableView instance.
in NIB simply drag and drop UIView
on top of that wier place the existing UITableVIew object.
set the size of the uitableview via nib or viewDidLoad method.
set the reference , dataSource and delegate via nib.
now its simply transfer the UIViewController class and the can change tableview size as you wish.
I'm trying to replace a UIViewController root view with a subclassed UIView.
In the iPhone SDK's UIViewController Class Reference, within it's Overview section, this is stated:
You use each instance of UIViewController to manage a full-screen view. For a simple view controller, this entails managing the view hierarchy responsible for presenting your application content. A typical view hierarchy consists of a root view—a reference to which is available in the view property of this class—and one or more subviews presenting the actual content.
Following the link on the view property it then states:
If your view controller does not have an associated view controller, you should override the loadView method and use it to create the root view and all of its subviews.
If this code was placed in loadView would it create the root view assuming I was using my own subclass of UIView called MyView:
self.view = [MyView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
Thanks // :)
You are correct. The loadView function is called when the view needs to be displayed, and the viewController's view property is the view that is displayed when using functions like presentModalViewController:animated:. If you are loading your view from a NIB instead of using loadView, then just change the class of the view to your custom subclass in the properties tab for that view.
You should note that anything you set the view property to gets retained. So you should either use
self.view = [[[MyView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
or
MyView *v = [[MyView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
self.view = v;
[v release];
to balance that out.
First a little background info:
I have UIViewController that contains a UITableView. In the loadView method (after initialization of the table), I set the UIViewControllers view to the table view with: self.view = tableView;
What I want is a view on the top of the screen (before the UITableView), that doesn't scroll with the rest of the table view when it is scrolled. I have tried adding my UIView to the table view's tableViewHeader, which displays correctly but scrolls with the rest of the table.
Is there any easy fix for this? Either way, any hints towards a solution is greatly appreciated.
EDIT:
Come to think of it, what I want is something like the stock application where the bottom part is stationary and the rest of the screen is a UITableView. The only difference is that I want the stationary part at the top of the screen.
As kmit has already pointed out, you can easily add more than one subview to your view. So, don't set the table view directly as self.view, but rather create a blank UIView (as container) and add the table view as well as the header view as subviews to that view. You can control the views' extents via their frame attributes. A simple example:
- (void)loadView {
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
[view setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth];
// header view
HeaderView* headerView = [[HeaderView alloc] initWithFrame:CGRectMake(0, 0, 320, 182)];
self.headerView = headerView; // in case you need the reference later on
[view addSubview:headerView];
[headerView release];
// table view
UITableView* tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 182, 320, 186) style:UITableViewStylePlain];
[tableView setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth];
tableView.delegate = self;
tableView.dataSource = self;
[view addSubview:tableView];
self.tableView = tableView;
[tableView release];
self.view = view;
[view release];
}
As an alternative to creating the containing UIView manually, you can call [super loadView] at the beginning of your loadView implementation.
Is there a reason you are setting the view of the UIViewController to that of the UITableView? Why not handle the UITableView as a subview? That would allow you to add anything you want above the UITableView -another view, empty space with the view of the UIViewController as your background, etc.