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;
}
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
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With