Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paging PFQueryTableViewController automatically

My goal is to setup the pagination with a PFQueryTableViewController. I would be satisfied with one of these solutions:

  • 1, Paging the table view automatically. As in instance, if objectsPerPage = 10 the tableView loads the next 10 objects when the actual row is the 10. row and so on.

  • 2, Paging with a "load more cell" UITableViewCell. As I see it is the popular solution, so I would also love this variation.

Actually I'm getting no errors when I try the second solution, it just simply doesn't work. I've added a new cell on the Storyboard and created a class for it, and checked the AnyPic and other related codes as a starting point. As I see I should display the LoadMoreCell cell when the number of the rows are less than the objects.count. I tried it several ways, but nothing works, I can't display the LoadMoreCell anyway.

Here's my try:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    if (indexPath.row < self.objects.count) {
        NSLog(@"THE NUMBER OF ACTUAL ROW %d", indexPath.row);
        NSLog(@"cell tapped");

    } else  { 

        // load more
        [self loadNextPage];
        NSLog(@"LOAD NEXT PAGE");

    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForNextPageAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *LoadMoreCellIdentifier = @"loadmore";
    LoadMoreTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LoadMoreCellIdentifier];

    if (!cell) {
        cell = [[LoadMoreTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:LoadMoreCellIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
        cell.loadMoreLabel.text = @"LOAD MORE CELLS";
        NSLog(@"NO CELL");
          }

    return cell;
}

The other part of my implementation is the last code part of the question.

My original question covers my attempts with the first (paging automatically ) variation.

My original question:

I have a working PFQueryTableViewController, but I'm unable to setup the pagination for it. My plan is simple, I want to load the next page when the user scrolled to the bottom of the table view. If the table displays 10 item/page I would like to display the next 10 item when the 10. cell appeared.

Actually I'm detecting when the user reached the bottom of the table and then call [self loadNextPage] for the new items, but the app crashes with this error:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 10 from section 0 which only contains 10 rows before the update'

I don't really understand this issue, because the datasource (an array) has more than 40 objects that can be loaded.

Here's how I manage the method call (pagination is enabled at initWithCoder)

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;
    float reload_distance = 10;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
        [self loadNextPageInTable];
    }
}

-(void) loadNextPageInTable {

     [self loadNextPage];
    NSLog(@"NEW PAGE LOADED");
}

And here is the table view setup

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        self.parseClassName = @"followClass";
        self.pullToRefreshEnabled = YES;
        self.paginationEnabled = YES;
        self.objectsPerPage = 10;
    }
    return self;
}


- (PFQuery *)queryForTable {
    if (![PFUser currentUser]) {
        return nil;
    }

    PFQuery *followQuery = [PFQuery queryWithClassName:@"self.parseClassName"];
    [followQuery whereKey:@"followed" equalTo:[PFUser currentUser]];

    return query;

}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.objects.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {


    static NSString *CellIdentifier = @"followCell";
    FeedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    cell.followLabel.text = object[@"username"];
    cell.avatar.file = object[@"image"];
    [cell.avatar loadInBackground];

    return cell;

}
like image 288
rihe Avatar asked Dec 02 '14 15:12

rihe


2 Answers

Here is the code that works in my test project. I do get the error that you get when numberOfRowsInSection is not commented out. I do see load more cell but it automatically loads the rest of the cells let me know if that helps

#import "ParseDataTableViewController.h"

@implementation ParseDataTableViewController


- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        // Custom the table

        // The className to query on
        //self.parseClassName = @"ParseTest";

        // The key of the PFObject to display in the label of the default cell style

        // The title for this table in the Navigation Controller.
        self.title = @"Test";

        // Whether the built-in pull-to-refresh is enabled
        self.pullToRefreshEnabled = YES;

        // Whether the built-in pagination is enabled
        self.paginationEnabled = YES;

        // The number of objects to show per page
        self.objectsPerPage = 15;
    }
    return self;
}




- (IBAction)nextPage:(id)sender
{
    [self loadNextPageInTable];
}

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;
    float reload_distance = 15;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
        [self loadNextPageInTable];
    }
}

-(void) loadNextPageInTable {

    [self loadNextPage];
    NSLog(@"NEW PAGE LOADED");
}


- (PFQuery *)queryForTable {


    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Name BEGINSWITH 't'"];
    PFQuery *followQuery = [PFQuery queryWithClassName:@"ParseTest" predicate:predicate];


    return followQuery;

}

/*-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.objects.count;
}*/



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {


    static NSString *CellIdentifier = @"DataCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    cell.textLabel.text = object[@"Name"];

    return cell;

}



@end
like image 93
Yan Avatar answered Sep 28 '22 22:09

Yan


In your cell creation you've got no way for the tableview to create a new cell if one does not exist already.

Create a new cell when one does not exist from the dequeuing mechanism:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {


static NSString *CellIdentifier = @"followCell";
FeedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//adds new cell if one does not exist already
if (!cell) {
    cell = [FeedTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    //TODO: edit cell details 
}


cell.followLabel.text = object[@"username"];
cell.avatar.file = object[@"image"];
[cell.avatar loadInBackground];

return cell;
}
like image 39
Brooks Hanes Avatar answered Sep 28 '22 20:09

Brooks Hanes