Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PFQueryTableViewController error

I'm following a tutorial online for creating a photo sharing app using Parse as a backend. I've run through the tutorial twice, creating the app from scratch both times, and still the same error occurs at the same spot. I've looked high and low for a solution and still no luck.

I'm using a PFQueryTableViewController, and my content is being loaded in multiple sections instead of rows. Each section displays PFUser details in the section header, and each section has only one row, which displays the image loaded by that user. At the end of each page (I have pagination enabled, loading 3 objects at a time) there is a "Load more" button to load the next 3 objects into the table view when clicked. However, when I click this button, my app crashes and presents this error:

Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2935.137/UITableView.m:1114 2014-07-28 01:50:37.368 SampleCamApp[25686:60b] Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 3 from section 0 which only contains 1 rows before the update'

Here's my code:

#import "HomeViewController.h"

@interface HomeViewController ()

@end

@implementation HomeViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        // This table displays items in the Todo class
        self.parseClassName = @"Photo";
        self.pullToRefreshEnabled = YES;
        self.paginationEnabled = YES;
        self.objectsPerPage = 3;
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self loadObjects];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - PFQueryTableViewDataSource and Delegates
- (void)objectsDidLoad:(NSError *)error
{
    [super objectsDidLoad:error];

}

// return objects in a different indexpath order. in this case we return object based on the section, not row, the default is row
- (PFObject *)objectAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.section < self.objects.count)
    {
        return  [self.objects objectAtIndex:indexPath.section];
    }
    else
    {
        return nil;
    }
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if(section == self.objects.count)
    {
        return nil;
    }
    static NSString *CellIdentifier = @"SectionHeaderCell";
    UITableViewCell *sectionHeaderView = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    PFImageView *profileImageView = (PFImageView *)[sectionHeaderView viewWithTag:1];
    UILabel *userNameLabel = (UILabel *)[sectionHeaderView viewWithTag:2];
    UILabel *titleLabel = (UILabel *)[sectionHeaderView viewWithTag:3];

    PFObject *photo = [self.objects objectAtIndex:section];
    PFUser *user = [photo objectForKey:@"whoTook"];
    PFFile *profilePicture = [user objectForKey:@"profilePicture"];
    NSString *title = photo[@"title"];

    userNameLabel.text = user.username;
    titleLabel.text = title;

    profileImageView.file = profilePicture;
    [profileImageView loadInBackground];

    return sectionHeaderView;
}


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSInteger sections = self.objects.count;

    if(self.paginationEnabled && sections >0)
    {
        sections++;
    }
    return sections;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
    if(indexPath.section == self.objects.count)
    {
        UITableViewCell *cell = [self tableView:tableView cellForNextPageAtIndexPath:indexPath];
        return cell;
    }

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

    PFImageView *photo = (PFImageView *)[cell viewWithTag:1];
    photo.file = object[@"image"];
    [photo loadInBackground];

    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if(section == self.objects.count)
    {
        return 0.0f;
    }
    return 50.0f;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.section == self.objects.count)
    {
        return 50.0f;
    }
    return 320.0f;
}


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

    return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.section == self.objects.count && self.paginationEnabled)
    {
        [self loadNextPage];
    }
}

- (PFQuery *)queryForTable
{
    PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];

    [query includeKey:@"whoTook"];

    [query orderByDescending:@"createdAt"];

    return query;
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

When I run my app, all content gets loaded correctly, including images, text, etc... Its only when I click the button that the trouble starts. I'm pretty cozy with iOS development at this point, however, I'm fairly new to Parse, and this is the first time I've used a PFQueryTableViewController. Please let me know if I'm implementing something incorrectly, otherwise I'll just have to work around a regular UITableViewController to make this happen.

like image 200
Shay Avatar asked Oct 01 '22 05:10

Shay


2 Answers

I think I'm doing the same tutorial as you.

I got this to work by deleting Parse.framework from my project, then downloading and importing the Parse.framework from "Lecture 25"

It must just be that the newer parse framework has changed in some way

like image 135
user781404 Avatar answered Oct 17 '22 00:10

user781404


one workaround is to tweak the custom PFQueryTableViewController.h file provided in ParseUI.

Simply include the following in your HomeViewController.m to override the Parse provided similar method(If it doesn't exist , add it to the PFQueryTableViewController.h under ParseUI.Framework>Headers Add this to the h.: - (NSIndexPath *)_indexPathForPaginationCell;

Call the code below in your .m file:

- (NSIndexPath *)_indexPathForPaginationCell {

return [NSIndexPath indexPathForRow:0inSection:[self.objectscount]];

}

Credit goes to a gentlemen by the name of Axel Wittmann .

like image 20
htjohn Avatar answered Oct 17 '22 00:10

htjohn