15

I am trying to implement loading data from my backend with pagination. I have seen this, but it loads all the data, all then time. Is this the right way or am I doing something wrong?

Thanks in advance.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell

    print(indexPath.row)

    if (indexPath.row + 1 < self.TotalRowsWithPages) {
        cell.textLabel?.text = "\(self.myarray!.[indexPath.row].body)"
    } else {

        cell.textLabel?.text = "Loading more data...";

        // User has scrolled to the bottom of the list of available data so simulate loading some more if we aren't already
        if (!self.isLoading) {
            self.isLoading = true;
            self.TotalRowsWithPages = self.TotalRowsWithPages + self.PageSize
            self.getmoredata()
        }
    }

    return cell
}
Sohil R. Memon
  • 9,404
  • 1
  • 31
  • 57
Chris G.
  • 23,930
  • 48
  • 177
  • 302

3 Answers3

39

Nope, you can't go with that approach because cellForRowAtIndexPath is called many times and also it will take much time to check your conditions!

Here, I have found a better option for UITableView pagination.

func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {

    //Bottom Refresh

    if scrollView == tableView{

        if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height)
        {
            if !isNewDataLoading{

                if helperInstance.isConnectedToNetwork(){

                    isNewDataLoading = true
                    getNewData()
                }
            }
        }
    }
}

isNewDataLoading is Bool to check that UITableView is loading new data or not!

Hope this helps!

Sohil R. Memon
  • 9,404
  • 1
  • 31
  • 57
5

You should implement load more in tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath). When last cell loading is display it mean user scroll to bottom so this is time you need load more data.

Maybe it looks like this:

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

    if !(indexPath.row + 1 < self.TotalRowsWithPages) {
        self.isLoading = true;
        self.getmoredata()

    }
}
vien vu
  • 4,277
  • 2
  • 17
  • 30
  • I have tried this approach. `willDisplayCell` is called irrespective of where the user is. when you reload data in tableview, willDisplayCell is called for every row. Accepted answer works perfect. – Awais Fayyaz Apr 21 '20 at 11:19
0

Try to check more data not in cellForRowAtIndexPath but in UIScrollViewDelegate - [DataModel sharedMyLibrary] is my data source class loading video data using RESTful API with pagination, it's fetchWithCompletion method fetch data from server in async, it's hasMore method says that server has more data (JSON contains next link) LibraryTableViewController - is subclass of the UITableViewController, hasMore - is the view at the bottom of the table view in the storyboard containing a button, so user has two options: scroll down or press the button. Also if this view is visible indicates that there are more data on the server. _canFetch prevents nested loading from the server.

``

@interface LibraryTableViewController () <UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIView *hasMore;
@end
@implementation LibraryTableViewController
{
    __block volatile uint8_t _canFetch;
}
@synthesize hasMore = _hasMore;
- (void)viewDidLoad
{
    _canFetch = 0x80;
    [super viewDidLoad];
    [self fetchVideos:NO];
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    CGPoint offset = [scrollView contentOffset];
    if ([[DataModel sharedMyLibrary] hasMore])
    {
        if (((velocity.y > 0.0) && (offset.y > (*targetContentOffset).y)) || ((velocity.x > 0.0) && (offset.x > (*targetContentOffset).x)))
        {
            [self fetchVideos:NO];
        }
    }
    else
    {
        [_hasMore setHidden:YES];
    }
}
- (IBAction)moreVideos:(UIButton *)sender
{
    [self fetchVideos:NO];
}
- (IBAction)doRefresh:(UIRefreshControl *)sender
{
    [sender endRefreshing];
    [[DataModel sharedMyLibrary] clear];
    [self fetchVideos:YES];
}
- (void)fetchVideos:(BOOL)reload
{
    if (OSAtomicTestAndClear(0, &(_canFetch)))
    {
        __weak typeof(self) weakSelf = self;
        [[DataModel sharedMyLibrary] fetchWithCompletion:^(NSArray *indexPathes) {
            dispatch_async(dispatch_get_main_queue(), ^{
                __strong typeof(self) strongSelf = weakSelf;
                if (indexPathes != nil)
                {
                    if (reload)
                    {
                        [[strongSelf tableView] reloadData];
                    }
                    else
                    {
                        [[strongSelf tableView] beginUpdates];
                        [[strongSelf tableView] insertRowsAtIndexPaths:indexPathes withRowAnimation:UITableViewRowAnimationAutomatic];
                        [[strongSelf tableView] endUpdates];
                    }
                }
                else
                {
                    [[strongSelf tableView] reloadData];
                }
                [strongSelf->_hasMore setHidden:![[DataModel sharedMyLibrary] hasMore]];
                strongSelf->_canFetch = 0x80;
            });
        }];
    }
}

``

  • 2
    The question belongs to `Swift` so please don't post unnecessary code. If you have the `Swift` code then go for it, otherwise delete the answer – Sohil R. Memon Feb 19 '16 at 04:18
  • @SohilR.Memon, the guy is trying to help, yes it is not `Swift` but the logic behind are the same. – 0yeoj Feb 19 '16 at 05:51
  • @0yeoj But still the guy has just post the complete code, how the person will understand. If he / she is trying to explain the logic then only that part should be mentioned in the answer. My intension is to just get the problem solved of the person who is asking question. No offence, though! – Sohil R. Memon Feb 19 '16 at 05:54
  • 1
    @SohilR.Memon, He has a caption above. But I get what you mean, he could have added comments and explained what's going on. (What if the person asking don't have knowledge about `ObjC`), at least we point this thing out... Cheers! ;) – 0yeoj Feb 19 '16 at 06:00