UITableViewCell size does not follow Content View size - uitableview

I have two UITableViewControllers which use the same set of cell templates, therefore I have created a table view controller in my Storyboard which contains these templates. My table view controllers instantiate an instance of this template holder tableview, then in -tableView:cellForRowAtIndexPath: they deque one of it's cells, and configure it as they need.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *widgetDict = [self.widgets objectAtIndex:indexPath.row];
DMSWidget *widget = [self.widgetStorageTableViewController.tableView dequeueReusableCellWithIdentifier:#"Key Value Row"];
...
return widget;
}
These cells have their inner layouts set up entirely using AutoLayout.
Everything works fine, except that I get cells which have the standard 44 px height and width of the table view, with Content Views narrower than this (depending which they contain, the ones with less contents are smaller), and are longer than the cells themselves. So the Content Views overlap the next cell but don't fill the entire width.
I don't understand, how this could happen. How is it possible, that the UITableViewCell has different size than it's Content View? They should be the same, isn't it?
What I tried to do but failed:
implement -tableView:heightForRowatIndexPath:: tried to return UITableViewAutomaticDimension, but did not help
reload my table view when the sizes are calculated: does nothing
add hacks to cell implementations, like setting autoresizingMask in -awakeFromNib: I could make the Content View expand to the width of the cell itself, but it was still overlapping to the next cell
UPDATE: It looks like it is not related to the dual table view architecture. When I copy my cell to the tableView where it will show up, has the same issues.

I've found the solution: it was all my fault. In some of the ancestors of my cell has an init, which called -initWithFrame: explicitly with CGRectZero. After removing this, iOS 8 could use it's frame values and everything worked fine.

Related

UITableView + UICollectionView + UITableView sizing issue

Below attached image is representing my requirement:
In this image the yellow color UITableView will have list of different UITableViewCell items. In one of the UITableViewCell it has UICollectionView with its list of UICollectionViewCell items and the scroll direction for the UICollectionView is set to horizontal
Each UICollectionViewCell will have one UITableView (Highlighted in Red Color) and it will have its list of UITableViewCell (Highlited in Rose Color) items. Here, the UITableViewCell (Highlited in Rose Color) item can collapse/expand. Whenever the cell is collapse/expand the red table's content size is handled automatically. But, whenever the red table's content size is increased the collectionview size is not increasing.
I have added all relevant constraints to these UI elements. But, the content size or frame of the collectionview is not expanding when a tableview cell is expanded.
To understand better here i am breaking it down how the views are designed:
Yellow tableview embedded inside a UIViewController and it will have one simple UITableViewCell which has no custom class
To the cell programatically the UICollectionView will be added. This UICollectionView is placed in one xib file and it has embeded inside a UIView
UICollectionViewCell has been created in one xib and it will have UITableView element inside.
Also, UITableViewCell has its own xib to refer and this is the cell which will gets expand/collapse
I have tried modifying the intrinsicContentSize property to modify the UICollectionView property's height where it has embedded inside UIView element whenever the expand is happening. Please, refer the CardView.swift for the reference.
CardView.swift
I know the design is bit complex. But, what am i missing here?
Based on your requirement in the image, I just created a sample project here.
I did not use separate Xibs. However, I was able to achieve what you asked for.
You might have to handle the reload of the innermost tableView better based on your apps business logic.
Here's what I have implemented:
The top most view controller has a parent table view.
This table view cell consists of a child collection view.
The child collection view cell consists of a grand child table view.
The grand child table view is the one corresponding to the table view Highlited in Rose Color in the question.
To answer your question about the collection view not expanding: to expand the child collection view when the grandchild table view cell is tapped, I am reloading the parent table view by increasing the row height for the cell containing the collection view. Hence you don't have to worry about adjusting the constraints in auto layout
In case you want to add additional content into the child collection view cell, you can add a height constraint to the grand child table view with a low priority and modify that whenever you need to expand the content in the grand child table view.
if you want to achieve point 6, as suggested by #Ramy Al Zuhouri, you might have to call: collectionView.performBatchUpdates before collectionView.reloadData() to expand the cell size
Refer to the video below for better understanding
This doesn't necessarily solve your problem, but sometimes it's a matter of forcing the collection view to invalidate its layout and recalculating its size. I once received an answer to a TSI from an Apple enginner:
So this is old fashioned way of forcing a re-usable container (Collection || Table) to invalidate its layout. You may even be able to just call invalidate layout. There are oddities in the system with AutoLayout and animations that sometimes throw the system into an odd state. If we do the above the container and can invalidate its layout and make updates without need to re-calculate + incorporate animations. To summarize, calling performBatchUpdates with nil parameters can be useful if you need to force an update based on layout content (not necessarily datasource changes).
It looks like a hack to be used with caution, but it can be worth to give it a try. Whenever you need to recalculate the size of the collection view's cell to expand or shrink, you can do this:
UIView.setAnimationsEnabled(false)
collectionView.performBatchUpdates(nil, completion: nil)
UIView.setAnimationsEnabled(true)
collectionView.reloadData()
This forces a reload, and UIKit is able to recalculate the height of the cell given that you update the height. How? In my case I did by updating a height constraint, but there are multiple ways of doing this. However, it's intended that as the reload happens the collection view should be aware of the new cell height.
the good approach for this, you have to add collectionView in the tableViewHeader
then whenever you scroll up your tableView your collectionView section will also scroll up
to load cells on the specific indexes follow bellow steps:
if(indexpath.row == 0){
//load first tableView cell with collection view
}
else if (indexpath.row == 1){
//load second tableView cell with collection view
}
else{
//load table view cell here
}

IOS/Objective-C: Reusing Cell Throws off Autolayout of Different Size Elements in TableviewCell

I am displaying feed items in a tableview. Depending on the item, the cell must be larger or smaller--for example larger to accomodate a photo or larger still if it references another feed item such as an article and I have to display the item referenced.
In most cases, I've used autolayout to get the cells to auto expand or contract based on the content. However, in a couple cases, this was proving next to impossible so I reset the value of a constraint in code. For example, if there is no photo in one case, I shrink the height of the cell in code as the cell was not shrinking on its own.
This works fine when the page loads. But when you scroll and reuse cells, it leads to weird effects such as the cell expanding vertically or lines being pushed into one another.
Some questions on SO suggest using the method:
-(void) tableView:(UITableView *)tableView didEndDisplayingCell:(IDFeedCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
//Undo changes here
}
The problem is I don't know how to undo changes. For example, if I made a cell smaller by setting
self.height.constant = 100;
Should I set it back to the constant value in storyboard?
What value can I set it to when I don't know what the next item to resuse the cell will need in the way of dimensions.
Thanks for any suggestions. BTW, autolayout shows no issues.

Grouped UITableView - remove 'Prototype Cells' header in interface builder

I have a UITableView placed on my view controller in IB, using 2 prototype cells and 'Grouped' style. There will only ever be 2 cells in the table, and no group header so I want to resize the height of the table view control to be just tall enough to accomodate the 2 rows (each of height 29) so I have room for my other controls on the VC. Problem is, when I resize the height of the table in IB, it always shrinks at the bottom and retains the 'Prototype Cells' label. This means to get the right height and position I have to lose visibility of my cell designs - see screenshot :
Is there anyway to turn off the 'Prototype Cells' group header label so I can resize my controls WYSIWYG style?
It will be more useful to show your code and what UITableView delegate methods you have implemented in your VC. Anyways, try this : set your header #property for the tableView to nil and if you get no result implement this:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return nil;
}
Hope this will work. Cheers
It is possible to change the uitableview to static in stead of dynamic cells. This allows you to add the cells in the layout editor. You can then make iboutlets to the cells and there content. The downside of this is that you will have to use a UITableViewController as root which in turn doesn't let you add anything else then cells, headers and footers.
You can still add the rest of your components in a separate sections and just set the cell to background to invisible. or you could load the controller grab the view and resize it and add it to another viewcontrollers view.

How to avoid cells background image from hiding the separator line between rows

In my table view I am using custom image for the UITableView cell's background. It works perfectly except for the fact it hides the row separator. And now there is no row visible.
Is there a way to increase the distance so that cells will get separated.
Please help!!!
Thanks,
Without seeing what you are seeing, it's a bit hard to tell. That said, you could try adding the separator to the image so that it shows up in the cell.
If you want to change the height of the cell, implement the -tableView:heightForRowAtIndexPath: method in the table view delegate. Just return the correct height for the row at indexPath. I believe there is also a way to set the rowHeight in the table view properties in interface builder if all cells will be the same, but I tend to stay away from IB when possible.
As far as my knowledge you can add a line image to the cell as a footer.So that you can see the separator
I believe you have to override the -setFrame: method in your custom cell and return the same frame with height minus 1 pixel.
Also be sure to call [super layoutSubviews]; in your -layoutSubviews method if you have overridden this method with some custom implementation.
LineSeparator may be invisible to you because of your background image in your cell. Try to change the style of your separator.
Alternative Way:
Otherwise You have to add a one pixel line to the bottom of your Custom cell background image by your designer and if it's still not visible in your tableView, then you have to increase a height for your cell in heightForRowAtIndexPath: method.
Make sure your view if you have one that is inside your Cell is exactly the same size as your cell's size.
Make sure:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
is setting your cell heights correctly for all cells.

Static table view cell's height in xib not being applied

I have created a static table cell in a .xib, however when it is displayed the cell height set in the xib is not being applied, instead the cell is being displayed with what looks like the default height for cells.
I have set things up as:
1) The table view controller derives from UITableViewController
2) The TVC is not contained within a xib and is created in code in the app delegate and added to a tab bar controller.
3) The TVC is created using initWithNibName:bundle: with the nib name supplied as the name of the xib containing the table view and the static table cell.
4) The TVC has an IBOutlet iVar of type UITableViewCell*
5) cellForRowAtIndexPath returns this iVar.
6) numberOfRowsInSection returns 1, numberOfSectionsInTableView returns 1;
7) The xib contains a table view, which is connected to the File's Owner's view. The File's Owner is set to my custom table view controller class.
8) The UITableViewCell in the xib is connected to the outlet of type UITableViewCell in the File's Owner.
9) THe Table view style in the xib is set to grouped.
10) The size of the Table View Cell shown in the size inspector is N, and this is where the problem is. If I change N manually or by resizing the cell visual representation then this size is not applied when the table is drawn. I have also tried setting the view Frame Rectangle height in the size inspector to match.
It doesn't matter what value N is, big or small.
11) The cell's height is not being set anywhere in the TVC, if I do set it using self.tableView.rowHeight then its height does change. But I do not want to set it explicitly like this, I want the height size in the xib to be picked up.
This has been driving me nuts for a few days, and reading several tutorials on table views (including Apple's table view programming guide, especially the section on static cells, whose instructions I followed in the first place to set everything up) has not given me any clues where the problem lies.
TIA
Implement heightForRowAtIndexPath and return the height of the UITableViewCell linked to in your IBOutlet.
Do you have - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath defined in your UITableView delegate?
You may want something like:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 30;
}
Try this post if you're still having trouble try this post: Setting custom UITableViewCells height
I had the same problem and everyone here and on other threads suggests writing code to fix the problem, which seemed wrong. What's the point of using IB if you have to write code to get the properties right?
The answer turns out to be very simple but took a bit to track down. In IB there are two places that row height can be set (just like there are two places to set it in code). One is on the table, the other is on the cell.
The place I was (incorrectly) setting it was the tableViewCell's "Row Height" property in the Property Inspector. Changing this value had no effect on row height at runtime.
Then I found and set the "Row Height" property of the TableView (one step up the object hierarchy) and viola, the row height is correct at runtime. Once this was working I turned off the override of Row Height on the TableViewCell (uncheck "Custom" on the Row Height property). I was afraid this might be evaluated on each cell, which would kill performance since all my cells are the same height.

Resources