iOS11 UITableview reloadRowsAtIndexPaths glitch - ios

Can anyone help me understand or solve this UITableView glitch in iOS11. I have managed to reproduce my issue in a fairly simple test case.
https://github.com/trapper-/iOS11-tableview-glitch
When reloading cells near the bottom of a tableview the reloaded cell will start to scroll weirdly and other cells start to move and hop around.
It gets much worse when reloading multiple cells, but I didn't want to complicate this simple example.
Edit: This issue only occurs in iOS11, works fine in iOS10 & iOS12. So
you need to download the iOS11 simulator to test this in Xcode 10

This should help:
[UIView performWithoutAnimation:^{
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}];

If I use like this, its working.
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 100;
}

Try providing estimatedRowHeight to 0 to table view on viewDidLoad. It works for me.

Please try setting you're table view estimatedRowHeight (in the viewDidLoad method):
self.tableView.estimatedRowHeight = 100;
The tableView.rowHeight is set to UITableViewAutomaticDimension by default but you need to set the estimatedRowHeight
From apple - "To enable self-sizing table view cells, you must set the table view’s rowHeight property to UITableViewAutomaticDimension. You must also assign a value to the estimatedRowHeight property. As soon as both of these properties are set, the system uses Auto Layout to calculate the row’s actual height."
You can check out:
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithSelf-SizingTableViewCells.html

Related

Changing Constraints of UITableViewCell, not affecting TableViewCell height in TableView

I am changing the constraint for Cell, But the height of the Cell remains same till deque, after dequeuing it gives correct result.
Any idea how can we reload the cell if the cell constraints are manipulated?
Using Rxswift for Cell View Model, but TableView is in Objc.
Thanks
It is always nice to share your code.
How are you changing the height of your cell? Are you using the heightForRowAtIndexPath delegate.
For changes to appear, I use this code.
[self.tableView beginUpdates];
[self.tableView endUpdates];
If this does not work for you, please share your code and I would update my answer accordingly.

reloadRowsAtIndexPaths updates the contentOffset Of the table view

I am trying to reload a particular row from the tableview but the contentOffset of the tableview is reset to (0, 0) after the reload. I tried to add [tableview beginUpdates] and [tableview endUpdates] around the reloadRowsAtIndexPaths but didn't change the behavior.
The question was asked over here Calling reloadRowsAtIndexPaths removes tableView contentOffset but it did not solve the problem. I am pretty sure that animation has nothing to do with this behavior. I am not sure how to maintain the content Offset of the tableview while still reloading the tableview row.
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
I'm guessing you've implemented tableView:estimatedHeightForRowAtIndexPath: and have it returning 0.
After reloadRowsAtIndexPaths:withRowAnimation:, the tableView determines its offset using the estimated heights given in tableView:estimatedHeightForRowAtIndexPath:. So unless the value you return there is accurate, implementing it will cause your tableView's offset to change after the reload. I had a similar problem and fixed it by removing my implementation of tableView:estimatedHeightForRowAtIndexPath:.
Updating the estimatedRowHeight and estimatedSectionHeaderHeight with more accurate values can also help alleviate this issue if you haven't implemented any of the estimated height delegate methods.
You can use the view inspector to find the heights of your cells and headers.

Inferring row height in heightForRowAtIndexPath

What I would like to do:
In the UITableViewController method heightForRowAtIndexPath I would like to infer the value of the row height rather than hardcoding it.
I set the value previously in the storyboard in Interface builder.
Wrong approach:
The following method is the wrong approach as it is called before the actual cell is created and hence it loops:
// wrong approach
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//AppTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"AppCel" forIndexPath:indexPath];
//int height = cell.frame.size.height;
// TODO: Make it more dynamic
return 112;
}
Approach I am thinking of:
Is there a way to load the cell main.storyboard document and infer the height value? Or is there some other approach?
Related questions search:
I found the following unanswered related question dating back to 2010. This other question is not of much use as it derives the height from the cell content rather than from the story board document.
The approach you had coded is actually not totally wrong. What is wrong is using dequeueReusableCellWithIdentifier:forIndexPath. Instead you want to use the simpler version dequeueReusableCellWithIdentifier which you can use to provide a prototype cell which you can configure, layout and then calculate the height.
If using purely iOS8, all this is done for you with the new auto layout. If you want to support iOS7 as well, then you need to do this manually.
The following link explains the process you need to use. I use this and it works great when you want to support both iOS7 and iOS8.
Using Auto Layout in UITableView for dynamic cell layouts & variable row heights
You also have to watch if you use size class based constraints in your cells as there is a less than obvious issue you have to work around to get the height correct. See Offscreen UITableViewCells (for size calculations) not respecting size class?
Yes you can.
You can use autolayout constraints and let the autolayout do the calculations for you.
check out AppCoda tutorial for this Link
If you have the cell in a xib (CP_Cell.xib) you can do that:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return ((CP_Cell *) [[NSBundle mainBundle] loadNibNamed:#"CP_Cell" owner:self options:nil].lastObject).frame.size.height;
}

Table View Cells jump when selected on iOS 8

I'm trying to update my apps for iOS 8 and one strange issue that I can't figure out is that whenever I press a table view cell (on a grouped table view) and push another view controller on to the navigation controller, all the cells of the table view jump. It's sort of like they all reduce their height a little bit.
Consequently, when popping the navigation stack and coming back to the original table view screen, the cells jump again, this time they increase their height and going to back to how they were originally.
I have tried using a UITableViewController, doing my own table view management, not using explicity section heights, removing all custom header views and frames, basically anything I could think of.
It's happening on all the iOS 8 emulators and on actual devices runnings iOS 8 both iPhones and iPads.
Any suggestions will really help.
Edit: removed video
Alright, so if you're using the default UITableViewCells and setting custom fonts for the textLabel and detailTextLabel, make sure you either set rowHeight for the table view or implement one of the UITableViewDelegate methods for e.g. tableView:estimatedHeightForRowAtIndexPath:
The same code has worked fine on earlier versions of iOS, but needs fixing on iOS 8 for some reason.
I had the exact same problem!
It seems like the iOS 8 SDK uses the estimatedRowHeight, after selecting a row, which then results in a wrong height for the whole tableview, which causes the jumping of the tableview itself.
Not setting the estimatedRowHeight property or implementing the delegate method will fix the jumping bug.
I have not found a clean solution to fix it yet.
I solved the jumping problem with the Storyboard alone:
TableView Row Height: automatic.
TableView Estimate: my_value (e.g. 75)
TableView Cell Row Height: my_value
self.tableView.estimatedRowHeight=0;
self.tableView.estimatedSectionHeaderHeight=0;
self.tableView.estimatedSectionFooterHeight=0;
You can achieve self-sizing with this code:
implement together:
tableView.rowHeight = UITableViewAutomaticDimension;
tableView.estimatedRowHeight = CGFloatValue (initial estimated height);
in your storyboard, add the correct constraint on you cells.
Note: the jump issue will still show sometimes.
the exact solution for this jump issue is implementing the delegate method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return CGFloat;
}

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.

Resources