UITableView not scrolling when not assigned to parents UIViewController view property - ios

I have put an UITableView inside a UIViewController and have copied code from UITableViewController over to my UIViewController to have it fulfill "Table data protocols" with UITableViewControllers default implementation and am following http://developer.apple.com/library/IOs/#documentation/UserExperience/Conceptual/TableView_iPhone/CreateConfigureTableView/CreateConfigureTableView.html#//apple_ref/doc/uid/TP40007451-CH6-SW10s chapter "Creating a Table View Programmatically" (with using ViewDidLoad instead of LoadView as I use IB and have a nib, I created an outlet for the UITableView named tableView).
Now in above links chapter the UITableView is assigned to self.view which is the UIView property of the UIViewController. Then scrolling the UITableView is working but the UITableView fills the entire screen hiding other view content such as an UIToolbar - probably as it is the sole content after being assigned to the view property.
If I omit the assignment, the other view content is in place an everything is sized properly, however the UITableView doesn't scroll.
How do I achieve scrolling of the UITableView inside an UIViewController with the UIVC having static content (such as a toolbar)?
Here's the relevant code:
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
tableView.delegate = self;
tableView.dataSource = self;
[tableView reloadData];
//self.view = tableView;
}

If you have other content in the view controller that you are adding in interface builder then this will be part of the UIViewController's .view property - when you assign the table view to this, you are removing all that content.
If your table view is appearing normally but is not scrolling (how about selection? Does that work?) you may have disabled user interaction on it.
You have mentioned in comments that there is nothing but empty cells in your table view - I think this is the cause of your problem. I have just created a sample project where I have added in a table view as a subview of the view controller's view, and scrolling is fine - this is with me populating 100 dummy rows in there. If I don't return anything for the datasource and delegate methods, then the table view does not scroll.

Related

EXEC_BAD_ACCESS on dequeuing cell from UICollectionView

I have a problem when dequeuing a UICollectionView cell from the storyboard.
I have a view controller with a collection view as one of the subviews. The VC is set as the collection view's data source and delegate. The collection view has a couple of prototype cells with identifiers set.
When doing this:
- (void)viewDidLoad {
[super viewDidLoad];
self.sizingCell = [self.collectionView dequeueReusableCellWithReuseIdentifier:#"CellId" forIndexPath:nil];
}
I get an EXEC_BAD_ACCESS on the self.sizingCell line.
Interestingly, when I created a new test project with a view controller containing a collection view and did the same thing in viewDidLoad, the collection view's cell was created with no issues.
Did anyone else run into a similar issue?

How to set my view as my TableViewheader?

I've created a view (with a searchbar and some buttons in it) to my UITableViewController. I've then created an outlet for the view in my ViewController.h file and synthasized it in my ViewController.m file.
Here's a screen shot of my current setup
I'm using
self.tableView.tableHeaderView = headerView;
And I'm using
- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return headerView;
}
But my view still scrolls up and down with the table, it doesn't seem to be set as the header properly?
"it doesn't seem to be set as the header properly" -- yes it is being set properly. That is how a table header behaves. If you don't want it to scroll, then you can do one of two things. Either add the view as a sibling view to a UIViewController (your view above, with the table view below), or, if you only have one section, you can use it as a section header which will stick to the top.

Is it possible to have a fixed uitableview Header while using sections?

This question should not be mixed up with this here.. These are two different things.
There is a good example how to use a UITableView Header on SO.
This all works fine and the main header is fixed on top as long as the style is set to plain.
But if I use sections, the main header no longer sticks to top and moves away while scrolling to the bottom.
In this method, I am returning the header for each section.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
In this method I am setting the height for the header section above:
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
In this method, I am setting the real table header.
- (void)viewWillAppear:(BOOL)animated {
...
self.recordTableView.tableHeaderView = headerView;
}
Is it even possible having a fixed table header, while using sections?
What is an alternative solution to this please?
If you want a UITableViewController (static cells/keyboard handling) and have a fixed header then you should use Containment. You can do this from a Storyboard by setting up a UIViewController with your fixed header and then using a Container View to embed the UITableViewController.
Once you have your containing view setup, you right-click drag from the Container View to the View Controller you want to embed - the UITableViewController in this case.
You can access and get a reference to the contained View Controller (the UITableViewController) from the Container View Controller by implementing the prepareForSegue:sender: method.
There’s no way to maintain the header of a tableView fixed, but
an useful approach when you need a unique header, is to use a UIViewController rather than a UITableViewController, and set the header (UIView) out from the tableView.
Something like this:
If you want to keep the class as a UITableViewController you can add your header as a subview to the tableview's superview. You will have to also push the tableview top inset down so your headerview doesnt hide the table.
Here is a sample code to put inside your tableViewController subclass (This example assumes your tableview controller is inside a navigation controller, so it pushes the view to below the navigation bar):
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.automaticallyAdjustsScrollViewInsets = NO;
}
-(void)addHeaderView{
CGFloat yPosition = self.navigationController.navigationBar.frame.origin.y + self.navigationController.navigationBar.frame.size.height;
mainHeaderView = [[UIView alloc] init];
const CGFloat mainHeaderHeight = 44;
[mainHeaderView setFrame:CGRectMake(0, yPosition, self.view.frame.size.width, mainHeaderHeight)];
mainHeaderView.backgroundColor = [UIColor redColor];
[self.tableView.superview addSubview:mainHeaderView];
[self.tableView setContentInset:UIEdgeInsetsMake(yPosition + mainHeaderHeight, self.tableView.contentInset.left, self.tableView.contentInset.bottom, self.tableView.contentInset.right)];
}
I haven't done this, but the first thing I would think to try is to place my tableview in a UIView and make my own header there in that UIView. Seems a trivial matter to make that view appear to be the header of the table and it would certainly stay put.

UITableViewController and TableView Height

I am inheriting my view controller from UITableViewController. I have a header (logo), content (uitableview) and now I want to display the footer (uitabbar). But for some reason UITabBar is not visible. The space is being occupied by the UITableView. How can I fix this?
UPDATE 1:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
self.tableView.tableFooterView = self.tabBar;
}
I'm not sure you can put a UITabBar as a footer of a UITableView.
"footer of the tableView" meaning it won't be visible until you scroll your UITableView all way down past the last cell to then see the footer -- the header and footer of a tableView scrolls with the tableView content itself). Anyway in term of UX this seems very strange.
You probably want instead your UITabBar to always be visible at the bottom of your screen (and not being dependant of the scrolling of your UITableView). To do this, simply use a UITabBarController... that will then contain your UITableViewController (as the viewcontroller associated with one of its UITabBarItem)
[EDIT] See also Apple's View Controller Programming Guide and its paragraph about TabBarControllers.

Fixed header to UITableview?

I've got a UITableView that I'd like to stick a 44px subview on top of. I tried tableViewHeader, but that scrolls with the rest of the table.
I tried searching and have found many people saying I need to add a UIView superview and then add my header and the UITableView to it. However I can't find an example on exactly how to do this. I tried making a new UIView subclass and laying out the subviews in IB, but I ran into trouble getting the table controller to link w/ the UITable (because I don't know enough about IB).
How can I do this with XIBs? Can someone provide an example?
Thanks for any help you guys can provide.
I finally figured this out right after posting. Figures. :)
Here's what I did, in case others run into the same problem:
Delete the existing UITableViewController and its XIB. They're junk. Get really mad while you do.
Make a new UIViewController subclass with a XIB
Open XIB in IB and add your header stuff and a UITableView to the UIView
In the IB Outlets for UITableView make sure you connect Delegate and DataSource to your File Owner
In the header for your view controller, be sure to add <UITableViewDelegate, UITableViewDataSource> to implement these protocols
Implement all the regular UITableView delegate and data source methods you know and love, but in your UIViewController instead of the way you're used to doing it through UITableViewController
After this things should work.
The problem is, UITableViewController's view property is the same thing as the tableView property. I had the same problem, wanting to put some fixed content above the table. I didn't want to change the base class, as it provides lots of great functionality I didn't want to lose or disrupt.
The fix is actually easy. The trick is to create custom set and get for self.tableView property. Then, in loadView, you replace the view with a fresh UIView and add the tableView to it. Then you're free to add subviews around the tableView. Here's how it's done:
In header:
#interface CustomTableViewController : UITableViewController
{
UITableView *tableView;
}
In .m:
- (UITableView*)tableView
{
return tableView;
}
- (void)setTableView:(UITableView *)newTableView
{
if ( newTableView != tableView )
{
[tableView release];
tableView = [newTableView retain];
}
}
- (void)loadView {
[super loadView];
//save current tableview, then replace view with a regular uiview
self.tableView = (UITableView*)self.view;
UIView *replacementView = [[UIView alloc] initWithFrame:self.tableView.frame];
self.view = replacementView;
[replacementView release];
[self.view addSubview:self.tableView];
//code below adds some custom stuff above the table
UIView *customHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 20)];
customHeader.backgroundColor = [UIColor redColor];
[self.view addSubview:customHeader];
[customHeader release];
self.tableView.frame = CGRectMake(0, customHeader.frame.size.height, self.view.frame.size.width, self.view.frame.size.height - customHeader.frame.size.height);
}
Enjoy!
Replace the TableViewController with a ViewController, inside it add a UIView with fixed height to place the fixed content you need, and below that add a UITableView.
Create an outlet to your TableView
#IBOutlet weak var tableView: UITableView!
You can reuse all the funcs you already have removing the override word for example
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCellWithIdentifier(cellId) as UITableViewCell!
c.textLabel?.text = "A title"
c.detailTextLabel?.text = "A subtitle"
return c
}
See this answer to add the automatic refresh control if you need it Pull to refresh UITableView without UITableViewController
As an option it is possible to embed UITableViewController as part of UI into another UIViewController with 'Container View' element (pick one in Interface Builder from the Object library (where all other views are) ).
This way you can use UITableViewController like ordinary view (in terms of positioning) and compose any layout you need without overwritting existing table view code
EDIT:
to further expand my answer, here are the steps to accomplish the described approach:
Open you storyboar in interface builder
Drag'n'drop a new ViewController element to the storyboard from Object Library to add a new controller.
As a child view, drag'n'drop Container View from Object Library and place it anywhere inside the ViewController
Container View creates another view controller and "embedded" segue as a connection. It's save to delete this viewcontroller and to connect the Container View with the required view controller (as per the questions it's UITableViewController)
To connect Container View with UITableViewController just select the container view and control+drag to the UITableViewController - select "Embed" in the popup menu
Now the controller will display inside the Container View with respect to the container's position and boundaries.
It's possible to get a link to the embeeded view controller - the system will fire "prepareForSegue" method of the host viewcontroller (created on the step 1 above) and the controller is in segue.destinationViewController property - one can customize it as required. Just make sure to set an identifier to the "embedded" segue in interface builder - this is the same process just like for any other segues.
Define a custom UIView in storyboard or xib, have a IBOutlet reference for that UIView in View Controller. In -(void)viewWillAppear:(BOOL)animated method write [self.tableView.superview addSubview:filterHeaderView];, here filterHeaderView is the IBOutlet reference for my header view which I want to add as fixed header in my tableview.

Resources