1

When I scroll to the bottom of my tableview and fetch more data with the next offset, i add the new objects to my data array. My tableview however reloads and returns to the first cell. I'm trying to prevent this.

enter image description here

enter image description here

- (void)fetchMovies {
    [MBProgressHUD showHUDAddedTo:self.view animated:YES];

    [self.networkingHelper fetchNowPlayingWithCompletionHandler:^(NSArray *objects, NSError *error) {

     if (error) {
         [self showErrorView:self.errorView];
     } else {
         [self hideErrorView:self.errorView];
     }

     [self.movies addObjectsFromArray:objects];
     self.displayedItems = self.movies;

     dispatch_async(dispatch_get_main_queue(), ^{
         self.isMoreDataLoading = false;

         if ([[NSThread currentThread] isMainThread]){
             NSLog(@"In main thread--completion handler");

             [self.refreshControl endRefreshing];
             [self.loadingMoreView stopAnimating];
             [MBProgressHUD hideHUDForView:self.view animated:YES];
         } else {
             NSLog(@"Not in main thread--completion handler");
         }
         });
       }

     ];
}

Edit Tried adding this

- (void)fetchMovies {
    [MBProgressHUD showHUDAddedTo:self.view animated:YES];

    [self.networkingHelper fetchNowPlayingWithCompletionHandler:^(NSArray *objects, NSError *error)
     {

         if (error)
         {
             [self showErrorView:self.errorView];
         }
         else
         {
             [self hideErrorView:self.errorView];

         }
         [self.movies addObjectsFromArray:objects];
         self.displayedItems = self.movies;


         dispatch_async(dispatch_get_main_queue(), ^{
             self.isMoreDataLoading = false;


             if ([[NSThread currentThread] isMainThread]){
                 NSLog(@"In main thread--completion handler");

                 CGFloat oldOffset = self.moviesTableView.contentSize.height;
                 [self.moviesTableView reloadData];
                 CGFloat onewOffset = self.moviesTableView.contentSize.height;
                 CGPoint new = CGPointMake(0, onewOffset - oldOffset);

                 [self.moviesTableView setContentOffset:new];

                 [self.refreshControl endRefreshing];
                 [self.loadingMoreView stopAnimating];
                 [MBProgressHUD hideHUDForView:self.view animated:YES];


             }
             else{
                 NSLog(@"Not in main thread--completion handler");
             }

             });
     }

     ];
}

Still scrolls to top

Himanshu Moradiya
  • 4,769
  • 4
  • 25
  • 49
mparrish91
  • 101
  • 3
  • 11

5 Answers5

1

You are setting

[self.moviesTableView setContentOffset:CGPointMake(0, self.searchController.searchBar.frame.size.height)];

in your addSearchBar method which is being called after load more completed, setting content offset at initial point.

Do also manage you setupInfiniteScrollView Where you are adding subview into Tableview.

And there is little bit changes with the logic

fetch this old y offset position

CGFloat oldOffset = self.moviesTableView.contentOffset.y;

Set the same Y position after load more like

CGPoint new = CGPointMake(0, oldOffset);
 [self.moviesTableView setContentOffset:new];
Devang Tandel
  • 2,988
  • 1
  • 21
  • 43
  • i am not getting you – Devang Tandel Dec 17 '16 at 09:18
  • Thank you this fixed it for me. Dumb error of setting the content offset elsewhere. I did not notice that didLayoutSubviews was called multiple times on table scroll. In layoutSubviews I had awn addSearchBar function. In it i offset my search bar at an initial point. – mparrish91 Dec 20 '16 at 03:09
0

Add line in your

if ([[NSThread currentThread] isMainThread]){
        NSLog(@"In main thread--completion handler");

       [self.refreshControl endRefreshing];

       NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[YOURARRAY.count] - 1 inSection:0];
       [self.YOURTABLLENAME scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

       [self.loadingMoreView stopAnimating];
       [MBProgressHUD hideHUDForView:self.view animated:YES];
 }
Himanshu Moradiya
  • 4,769
  • 4
  • 25
  • 49
0

You need to use dynamic insertion of rows after receiving your data:

NSMutableArray *arrayOfInsertedIndexes = [NSMutableArray array]; 
NSInteger currentCount = self.yourOldData.count; 
for (int i =0; i < yourNewData.count; i++) 
{ 
      [arrayOfInsertedIndexes addObject:[NSIndexPath indexPathForRow:currentCount+i inSection:0]];
}
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:arrayOfInsertedIndexes withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];

Do not use

[self.tableView reloadData];
0

The problem is that after reloadData contentSize doesn't change synchronous. You should call layoutIfNeeded after reloadData. And only after that contentSize changed

Try this

//.....
 if ([[NSThread currentThread] isMainThread]){
     NSLog(@"In main thread--completion handler");

     CGFloat oldOffset = self.moviesTableView.contentSize.height;
     [self.moviesTableView reloadData];
     [self.moviesTableView layoutIfNeeded];
     CGFloat onewOffset = self.moviesTableView.contentSize.height;
     CGPoint new = CGPointMake(0, onewOffset - oldOffset);

     [self.moviesTableView setContentOffset:new];
     [self.refreshControl endRefreshing];
     [self.loadingMoreView stopAnimating];
     [MBProgressHUD hideHUDForView:self.view animated:YES];
//.......
Nick Rybalko
  • 202
  • 2
  • 5
0

Objective C:

 NSIndexPath* ip = [NSIndexPath indexPathForRow:rowNumberHere inSection:sectionNumberHere];
[theTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO];

Swift:

 let offset = CGPoint(x: 0, y: self.tableView.contentSize.height - self.tableView.frame.size.height + self.FOOTERHEIGHT);
 self.tableView.contentOffset = offset;
Vinit Ingale
  • 381
  • 1
  • 4
  • 17