views:

151

answers:

3

I am using iPhone SDK 3.1.3. I have a UITableViewController which gets data from another controller. The tableview is added as a subview to the mainview but the frame is set so that it is not visible. The tableview frame is updated and made to slide over the main view by tapping on a button.

The table view appears and i scroll to the last row. if i select the last row, i reload the table with more data. The table gets updated with more data. everything works fine except the scroll position is always the top.

I need the scroll position to be the last row that I clicked on to load more data. I save the scroll position and call the following code after it loads more data. It executes without issues but the scroll position is always the top.

 [theTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:savedScrollPosition inSection:0] atScrollPosition:savedScrollPosition animated:NO];

The above seems to have no effect. ViewWillAppear: ViewDidAppear: does not fire and I am told that if the view controller is instantiated in code, which is the case, these don't fire. Please help me figure out how and when to set the scroll position after the table is reloaded ([theTableView reloadData]) so that it is at the row that I clicked on.

Code to Reload tableview & scroll

 ////performAction will notify the tableviewcontroller which will result in didPerformAction being called
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
     if (indexPath.row == lastRow)
     {
       savedScrollPosition = lastRow;
       //perform the action
       [controller performAction];
     }
}

- (void) didPerformAction:(NSNotification *)obj
{
  [theTableView reloadData];
  [theTableView
     scrollToRowAtIndexPath: [NSIndexPath indexPathForRow:savedScrollPosition inSection:0]
     atScrollPosition:UITableViewScrollPositionBottom 
     animated:NO];
}
A: 

If that's the actual code and assuming theTableView is not nil there, you should be getting a warning saying "may not respond to..." because scrollToRowAtIndexPath is spelled wrong.

Secondly, the atScrollPosition parameter expects a UITableViewScrollPosition enum value indicating where on the screen you want the target row to be positioned.

Try this:

[theTableView scrollToRowAtIndexPath:
                [NSIndexPath indexPathForRow:savedScrollPosition inSection:0]
                atScrollPosition:UITableViewScrollPositionBottom 
                animated:NO];
DyingCactus
sorry that was a typo. I have edited it. well, I don't want to scroll to the bottom. I need to scroll to the row that I clicked on which is kind of the middle but not the middle everytime. Nevertheless, i tried this and weirdly, it still stays at the top.
Dave
Show the method where this is called. Put NSLogs before the call showing the value of savedScrollPosition. atScrollPosition does not refer to the row number but to it's current relative position on the screen.
DyingCactus
oh i see. i updated the code.
Dave
Does the reloadData get called and do you see the additional data? Log the value of savedScrollPosition after the reloadData line and confirm it is the row that had been selected.
DyingCactus
yes. reloadData loads more data and savedScrollPosition is updated as expected.
Dave
was reading about tableview bounds and if the height is more than the actual view bounds, the scrolling doesn't happen. I tried setting the height to much lower value and i still see the same behaviour
Dave
Ok but you're able to manually scroll the tableview after the reload right? I was not able to duplicate the problem with a project based on your description of the layout and code. Try starting with a fresh project that just tests the scrollToRowAtIndexPath and then one at a time add the other elements.
DyingCactus
Thanks! weird as it seems, i had to set the contentOffSet. I have added my answer.
Dave
Thanks for the update. drawnonward gave a good answer.
DyingCactus
+3  A: 

It will look better and the scroll position will stay fixed if you can insert the rows instead of calling reloadData.

[theTableView beginUpdates];
[theTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:animation];
// make sure the dataSource will return new rows before calling endUpdates
[theTableView endUpdates];

Instead of using UITableView scrolling you can use UIScrollView scrolling:

savedOffset = [theTableView contentOffset];

Then restore:

[theTableView setContentOffset:savedOffset];
drawnonward
oh thanks, I just posted the answer which is mostly same as yours, setting contentOffset. Thanks for your insert row tip.
Dave
A: 

This seemed to do the trick.

[theTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:savedScrollPosition inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];                        
    CGPoint point = theTableView.contentOffset;
    point .y -= theTableView.rowHeight;
    theTableView.contentOffset = point;
Dave