UIViewController takes up entire screen in Interface Builder - iphone

I have a NIB with a UIView that contains some UILabels, UIButtons etc. and a UIViewController that is loading a UITableView from a detached NIB.
I want the UITableView in the UIViewController to be positioned below my UIView, but whenever I add it in Interface Builder it takes up the whole screen, and my UIView becomes part of the UIViewController.
How can I make sure the UITableView in my UIViewController appears below the UIView?

I want the UIViewController to be
positioned below my UIView
What you mean is you want the UIViewController's view positioned below your existing UIView. View controllers do not show up on screen themselves.
Create a new UIView instance in your nib, position it where you want, and assign it to be the view for the view controller.

Related

UINavigationController set view height?

I subclassed UINavigationController and added a UIView to the bottom of its view in viewDidLoad (as a custom UITabBar or UIToolbar).
How do I set the height of the view of every UIViewController that this UINavigationController pushes?
How do I set the height of the view of every UIViewController that
this UINavigationController pushes?
View controllers don't have height -- the views they manage do.
To do what you propose, I suppose you override the accessors for the delegate property so that you could intercept any calls to -navigationController:willShowViewController:animated: and resize the child view controller. That doesn't seem like a very satisfying solution, though.
Do you have so many view controllers that you can't add your tool bar to each one's view hierarchy?

iPhone - placing tableview within a view in another nib. Window-based

I created a window based application, and I created a separate UITableViewController file called "HomeViewController" which right now only has a basic table.
In the MainWindow.xib file, I put a UIView in the bottom half of the screen, and I wish to put the HomeViewController tableview within this newly added UIView called "conferences".
Any suggestions as to how to push this file?
First off, usually your primary first view originates from a view controller that is loaded by the UIApplication object. The MainWindow nib's owner is UIApplication so you probably don't want to be mucking with the MainWindow nib. Rather, you want to muck with the view of the view controller loaded by MainWindow nib. If you look at the view displayed in IB for MainWindow.nib, it should say which view controller's view it is loading.
So, in IB for the view of view controller being loaded by MainWindow nib, this is where you want to place your UITableView. For purposes of this explanation, I will call this view controller, MucksViewController and associated nib, MucksView.nib.
I think what I would do, then, is drag and drop a UITableView into the view for MucksView.nib. Position it in the bottom half of the screen, as you described. Attach this UITableView to an IBOutlet property in MucksViewController header file. Next, drag and drop a UIViewController object into the main window for MucksView.nib. Make this UIViewController object's owner your HomeViewController class and also attach it to an IBOutlet property of type HomeViewController in MucksViewController's header file.
Now, in MucksViewController's class file, probably in viewDidLoad method, programmatically make the HomeViewController object the data source and delegate of the UITableView object.
But, I'm wondering, do you really need HomeViewController? It would be cleaner just to make MucksViewController the data source and delegate.
I hope this helps and is not too confusing.
Instead of a UITableViewController, use a UIViewController which implements the tableview delegate and datasource. in your MainWindow.xib, add a standard uitableview as a subview to the view where it should be. then also drag a HomeViewController to the xib (which should now be a uiviewcontroller sub class). click on the tableview, open the inspecor, go to connections, and drag the delegate and datasource to the HomeViewController in the xib.

UINavigationController -> UIViewController -> UIView -> UITableViewController?

Inside Interface Builder I have a UINavigationController, which contains a UIViewController, which has a UIView inside it. This main UIView has a bunch of labels as well as a few ImageViews and custom UIViews as well.
What I want to do though is throw a UITableView inside this main UIView. This UITableView will take up about half the screen in the UIView. I'm trying to add a UITableViewController below the UIView but everytime I do it, the UITableViewController object replaces my UIViewController object in IB??
What am I doing wrong?
I want:
UINavigationController
UIViewController
UIView
UITableViewController (since the UTableView will be inside the preceding UIView)
Where am I going wrong in this setup? When I try to add the UITableViewController in IB I get:
UINavigationController
UITableViewController (..err? Why's it replacing my ViewController?)
Thanks in advance!
After putting UITableView into UIView instead of UITableViewController, and then set table view's delegate and data source to UIViewController.
Naturally, UIViewController should implements two protocol (table view deleate and data source).
You probably don't need table view controller at all. You have to add UITableView and implement all necessary data source and delegate methods in your view controller.

Adding UIView subview to single table view controller in navigation stack

I'm working on an app that has three table view controllers in a navigation stack. The root view controller and the second VC have toolbars, but I want to add a subview to the second view controller like this. (The color is just there for visualization.)
I want to add the view programmatically, since I haven't been able to do it with IB without major headaches. Right now, I've been able to kind of get what I want by drawing a UIView in the second view controller like this:
- (void)viewDidLoad {
[super viewDidLoad]
UIView *detailView = [[UIView alloc] initWithFrame:CGRectMake(0, 392, 320, 44)];
detailView = [UIColor redColor];
[self.navigationController.view addSubview:detailView];
[detailView release];
}
The problem with this approach is that once the UIView is loaded in the second view controller, it stays loaded and is drawn in the third and root view controllers. I've tried a variety of methods of removing the UIView, including setting the detailView to nil in viewDidUnload, calling removeFromSuperview in didSelectRowAtIndexPath (which removed the view from the whole stack).
I've also tried adding the subview to self.view, but that pushes it below the visible area of the table view, so I have to scroll up to see it, and it snaps back down when I let go.
Clearly, adding this subview to the navigation controller is not the best way to do what I want, but I'm at a loss as to where to go from here.
As you've already discovered, you definitely should not be reaching up into the navigation controller's view.
You want your SecondViewController to be an UIViewController that implements the UITableViewDelegate and UITableViewDataSource and whose view lays out the UITableView and the UIView you wish to use for your stationary 'footer' in it's own main UIView.
It helps to keep in mind that UITableViewController is ultimately is just a convenience for creating a view controller whose view consists entirely of a UITableView.
Anyway, rather than attempt to put a pile of that code inline in this answer, you can browse it (or svn co) from this read-only svn repo.
EDITED (now that it's not midnight, putting some code/explanation directly in answer):
For the controller to be pushed onto the nav stack that needs the footer create a new UIViewController-based class (do NOT check the 'UITableViewController subclass' box in the template selection dialog).
Add instance variables for the UITableView and the UIView that is to be the extra bottom view.
#interface SecondViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
UITableView* tableView;
UIView* customFooterView;
}
#property (nonatomic,retain) IBOutlet UITableView* tableView;
#property (nonatomic,retain) IBOutlet UIView* customFooterView;
#end
In IB add a UITableView and UIView to the existing root view for the controller and lay them out as desired (probably worth altering the auto-resize parameters too if your app can be used in both landscape and portrait). Hook up the two views to the outlets defined for them in the "File's Owner" and also ensure you hook up the UITableView's delegate and dataSource properties to point at the "File's Owner."
Then just implement the UITableViewDelegate and UITableViewDataSource protocols as appropriate for your application.
If you want to lay out the entire 'footer' view in IB then go right ahead. Otherwise you can easily add items programmatically in viewDidLoad (and remember to tear it down in viewDidUnload).
I don't like the approach. You should put your table view inside another view, and put your detail view together in that view.
Despite of that, I think you can remove your view in viewWillDisappear method of your view controller. I also notice that you did not keep your detailView as a private variable, which you should do because you need to reference it when removing it later (I still wonder how you have done it.)
Note that viewDidUnload is called in case of view unloading (i.e. releasing from its controller), so it is not related to navigation.
Not sure which behavior you're looking for but try one of these:
Assign the detailView to the tableFooterView property of the tableview on the second VC.
Reduce the height of the table view and add the detailView to self.view.

How can I modify an existing UIViewController to allow scrolling?

I have already built a UIViewController subclass with a bunch of controls in it, and just realized that if I rotate the iPhone, half of the controls become invisible. So, I would like to somehow make the UIViewController's UIView scrollable so that when the device (or the Simulator) rotates, the user can scroll the view to see all the controls.
I was hoping to do this all in Interface Builder. I tried to change the class of the view from UIView to UIScrollView in the Class Identity editor, but nothing scrolls. The base class of my view controller is a simple UIViewController <UIScrollViewDelegate>.
Is there an easy way to make the main view in my view controller scrollable without having to recreate the whole thing in IB?
For people who are using storyboard, this is quite easy to do
in Document Outline select the topmost View of the UIViewController
then in Identity Inspecter, under Custom Class, for class enter UIScrollView
That's it.
Add a UIScrollView and make all your controls and widgets and labels subviews of the scroll view by dragging them from wherever they are "into" or "inside" the scroll view. This makes them subviews of the scroll view, which is what you want.
You can do this as follows:
Open your nib file and Create a UIScrollView object under your UIView Object.
Move all your controls onto the UIScrollView
Open your header file (.h) and add a new property for the scroll view:
#property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
Open your implementation file (.m) and insert the following:
#synthesize scrollView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Enable scrolling for portrait
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, 600);
}
Go back to your nib file and wire up the scrollView on the file's owner to your UIScrollView object.
The real trick here is setting the scrollView.contentSize. Once this is set, the scrolling should occur.
If you wanted to enable scrolling for when the device is in portrait orientation, you could use this:
// Enable scrolling for landscape orientation
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, scrollView.frame.size.height);
This should give you some frame of reference.
Flea
It would be helpful to understand what your interface is displaying, but I'd suggest one of the following:
Don't allow rotation by returning NO from shouldAutorotateToInterfaceOrientation
Use Interface Builder to adjust your springs and struts so that all of your interface elements fit in landscape view
Add a new UIScrollView in Interface Builder and drag your UIView into it, then re-assign the view property of your File's Owner to the scroll view.
I was able to do this by adding a scroll view to the view in IB, making the view controller a UIScrollViewDelegate, hooking up the scrollview to a UIScrollView object in IB, hooking the delegate up to file owner, and adding this line in the viewDidLoad:
- (void) viewDidLoad {
scrollView.contentSize = CGSizeMake(1280, 960);
}
Scrolling behavior is only invoked if the contentSize of a UIScrollView is larger than its bounds.
Add a Scrollbar into Xib file and then drag & drop controls in to the Scrollbar. Inside load view use
scrollView.contentSize = CGSizeMake(CONTENT_WIDTH, CONTENT_HEIGHT);