Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableViewController weird behavior after popping a view controller

My UITableView has a bunch of reusable cells, and when I tap on one of them, it takes me to another view controller (via push segue) showing the details of that cell (let's say it's an item, so it would show details about an item - name, price, image, etc...). When I pop that view controller (by tapping on the back button), the UITableView has a strange behavior:

a) if it's scrolled all the way to the bottom, it will scroll automatically tad up (around 50 points), leaving the last cell barely visible, so I have to scroll back down again. My cell all have 60 points for height.

b) the scrollbar always shows and then disappears, indicating that something is moving that UITableView (although if not scrolled to the bottom, the content will not move automatically).

This happens in multiple UITableView's I have in my app. I am not forcing a reload of the table view in viewWillAppear, so I don't understand what is happening. My content is static after loading from the server (unless the user changes it, and then the reload is executed). But simply showing details of an item and popping that VC doesn't change anything in the table view.

Edit: Okay, I've figured what the problem is: I'm hiding a UIToolbar when pushing that segue. If I keep it always visible (which I don't want), it still shows the scrollbars animating when popping in my table view but doesn't scroll the table view if on the last few rows.

like image 411
swiftcode Avatar asked Jul 12 '13 14:07

swiftcode


3 Answers

Add the following to viewDidLoad.

self.automaticallyAdjustsScrollViewInsets = NO;

This solved my problem of table view moving down after navigating back to view controller.

like image 62
Prasad Avatar answered Nov 06 '22 01:11

Prasad


I managed to fix the first issue. It seems like the tableview is not taking into account the 44 points of the UIToolbar.

Save the tableview offset in prepareForSegue: (save it in a CGPoint property)

self.tableViewScrollOffset = self.tableView.contentOffset;

Then, in viewWillAppear:, check if it has been modified. If so, restore it.

if(self.tableView.contentOffset.y != self.tableViewScrollOffset.y) {
        [self.tableView setContentOffset:self.tableViewScrollOffset];
        self.tableViewScrollOffset = CGPointZero;
    }
like image 3
swiftcode Avatar answered Nov 06 '22 03:11

swiftcode


This behavior is indeed a bug in iOS 8.x.

All answers given so far can not really solve the issue. The issue is, that iOS forgets (or doesn't) consider the previously calculated cell sizes, when a table is being redrawn for instance when the view is being pushed.

One approach to solve this can be found here: UITableView layout messing up on push segue and return. (iOS 8, Xcode beta 5, Swift) (so this question is even a duplicate to this one).

However, the solution provided there is overkill and there are certain situations why this caching will fail (for instance a UIContentSizeCategoryDidChangeNotification is not regarded)

But there is a quite simpler solution even though it is odd:

If you are using a manual performSequeWithIdentifier in didSelectRowAtIndexPath, just add a [self.tableView reloadData] just before.

If you are using a IB seque from the cell, just add [self.tableView reloadData] in your prepareForSeque code.

The reason, why this solves the issue is, that this will force iOS to re-estimate the visible cells and so it no longer scrolls the content to another location. Fortunately, tableView reloadData doesn't cost too much overhead here as only the visible cells will be re-estimated.

like image 3
Marcus Avatar answered Nov 06 '22 02:11

Marcus