Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UItableview scrollToRowAtIndexPath not displaying last row correctly

I have a tableview with custom cells with dynamic cell heights depending on the cell content.

My problem is the following, when I ask, programmatically, in the viewDidLoad, to scroll to a given position it works, except for the last row. Sometime the row appears but not fully, and sometimes it even does not appear. In both cases I have to scroll manually to see the row.

Here is the code :

[self.tableView reloadData];

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:aRow inSection:aSection];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES ];

Is this a bug of iOS ? any workaround ?

like image 625
HpTerm Avatar asked Oct 23 '12 10:10

HpTerm


2 Answers

As so far i came to know that,

All the operations used to before the view is shown on the screen are initialized in the viewDidLoad all the UI objects, data objects can be allocated and initialized in this method.

All the operations data modifications, UI modifications made to view need to be done in viewDidAppear. Or even some operations can be done in viewWillAppear.

So for your issue, the UITableView scrolling must be done after the table is loaded on & shown on screen i.e., in viewDidAppear.

Also note that viewDidAppear & viewWillAppear will be called each time view is shown to user, so if you want to scroll the table only for the first instance you can have a flag in your header indicating the instance.

like image 156
vishy Avatar answered Sep 27 '22 01:09

vishy


[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
        NSIndexPath *rowIndexPath = [NSIndexPath indexPathForRow:3 inSection:0];
        [self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
});

I don't know exactly why, but I guess this approach works because when we add(???) rows and call [tableView reloadData] tableView has no time to update some internal counters (like row counter) and calling [tableView scrollToRowAtIndexPath ...] has no effect since there is no such row at that time (again, probably correct in case you add rows or set tableView's data for the first time). Calling

dispatch_async(dispatch_get_main_queue(), ^{
    ...
}); 

after [tableView reloadData] gives tableView enough time to update row counter and perform scroll to existing row.

Vishy's approach works just because it gives enough time but applicable only if you need to scroll exactly one time when screen is loaded. Moreover it requires ugly flag to check every time viewDid/WillAppear.

like image 33
Fyodor Volchyok Avatar answered Sep 26 '22 01:09

Fyodor Volchyok