简体   繁体   中英

Where to Reload UITableView Data after parse query

I am having trouble getting my UITableView to reload appropriately. My app sometime works and other times it crashes because one of the data elements is not properly stored in an array when the tableView tries to update. Can someone point me out the proper place to reload my tableView please.

- (void)viewDidLoad {
 [super viewDidLoad];
[self queryForNewBooks];}

-(void)queryForNewBooks{
_bookNameArray = [[NSMutableArray alloc] init];

_authorNameArray  = [[NSMutableArray alloc] init];
_isbnNumberArray = [[NSMutableArray alloc] init];
_bookImageData = [[NSMutableArray alloc] init];

PFQuery *query = [PFQuery queryWithClassName:@"BooksForSale"];
[query orderByDescending:@"createdAt"];
[query findObjectsInBackgroundWithBlock:^( NSArray *objects, NSError *error) {

    if (objects.count >=1) {

        for (PFObject *object in objects) {
            PFFile *imageFile = [object objectForKey:@"image"];
            [imageFile getDataInBackgroundWithBlock:^(NSData *result, NSError *error) {
                if (!error) {
                    NSData *data = result;


                    NSLog(@"HEYYYYYY");
                    if (data == NULL) {

                    }
                    else{
                    [ _bookImageData addObject:data];

                   //I have tried placing it here [self.tableView reloadData] 



                    // NSLog(@"%@",[_bookImageData objectAtIndex:0]);

                    }


                }

            }

             ];

            NSDictionary *bookNameDictionary = object[@"nameOfBook"];
            NSDictionary *authorNameDictionary = object[@"Author"];
            NSDictionary *bookImageDictionary = object [@"image"];
            NSDictionary *isbnNumberDictionary = object [@"isbnNumber"];
            NSString *objectID = [object objectId];

            if  (bookNameDictionary != NULL){
                NSLog(@"Yo bro here is the book name   %@",bookNameDictionary);


                [_bookNameArray addObject:bookNameDictionary];
                NSLog(@"number: %@", bookNameDictionary);
            }

            if (bookNameDictionary == NULL) {
                [_bookNameArray addObject:@""];
                NSLog(@"Blank space");

            }

            if (authorNameDictionary != NULL) {
                [_authorNameArray addObject:authorNameDictionary];
                // [_tableData addObject:ft];
                NSLog(@"Author Name : %@",_authorNameArray);
                //  NSLog(@"the table data is %@",_tableData);
            }
            if (authorNameDictionary == NULL) {
                [_authorNameArray addObject:@""];
                NSLog(@"Blank space");

            }

            if  (isbnNumberDictionary != NULL){
                NSLog(@"Yo bro here is the isbn %@",isbnNumberDictionary);


                [_isbnNumberArray addObject:isbnNumberDictionary];
                NSLog(@"number: %@", isbnNumberDictionary);
                //[self.tableview reloadData];
            }

            if (isbnNumberDictionary == NULL) {
                [_isbnNumberArray addObject:@""];
                NSLog(@"Blank space");

            }

         /*   if (bookImageDictionary !=NULL){
                [_bookImageData addObject:bookImageDictionary];

            }
            if (bookImageDictionary ==NULL){
                [_bookImageData addObject:@""];
                NSLog(@"Blank Space");
            }*/
            if (objectID != NULL) {
                [_objectIDArray addObject:objectID];
                NSLog(@"object id is : %@",objectID);
            }
            if (objectID ==NULL){
                [_objectIDArray addObject:@"blank"];
            }

        }
    }
    // code
}];
 //I have tried placing it here [self.tableView reloadData]   

);

 }


 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.bookNameArray count];

}


(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
   static NSString *simpleTableIdentifier = @"TableViewCell";

 TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"TableViewCell" owner:self options:nil];
    cell = [nib objectAtIndex:0];
}
NSLog(@"Here are the book names, %@",_bookNameArray);

cell.bookNameLabel.text = [_bookNameArray objectAtIndex:indexPath.row];
cell.authorNameLabel.text = [_authorNameArray objectAtIndex:indexPath.row];


if ([_bookImageData objectAtIndex:indexPath.row] != NULL ) {
    NSLog(@"it seems to work");
   UIImage *image = [UIImage imageWithData: [_bookImageData objectAtIndex:indexPath.row]];
   cell.bookImageLabel.image = image;
}
else{
    NSLog(@"Error");
}
    return cell;
}

Updating question: Is this the proper way to declare a PFimageView? Can I just drag a UIImageView in the Xib file and then change its class to PFImageView? After changing it to a PFImageView should I be able to just link the view to the outlet as normally done?

#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import <ParseUI/ParseUI.h>



@interface TableViewCell : UITableViewCell

@property (nonatomic, weak) IBOutlet UILabel *bookNameLabel;
@property (nonatomic, weak) IBOutlet UILabel *authorNameLabel;
@property (nonatomic, weak) IBOutlet PFImageView *bookImageLabel;
@property (nonatomic, weak) IBOutlet UILabel *priceOfBook;


@end


#import <Parse/Parse.h>
#import "TableViewCell.h"
#import <ParseUI/ParseUI.h>

@implementation TableViewCell


@synthesize bookNameLabel =_bookNameLabel;
@synthesize authorNameLabel = _authorNameLabel;
@synthesize bookImageLabel = _bookImageLabel;

- (void)awakeFromNib {
// Initialization code
}

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

// Configure the view for the selected state
}

@end

The part that complicates the code is the need to fetch images using the objects returned by the query. The simplest solution is to omit the image fetching from the query completion handler.

  1. Instead, loop the returned objects, building the arrays (there's room for improvement here, too, but just sticking with the crash part of your problem for now). In the _bookImageData array, don't try to keep images, instead keep the PFFile for each object...

     // in the loop of objects, omit getDataInBackground and just do... [_bookImageData addObject:object[@"image"]]; 
  2. The answer to the stated question -- where to reload the table -- is after the loop that builds the table datasource.

     for (PFObject *object in objects) { // code to build all of the arrays, omitting getDataInBackground // ... } [self.tableView reloadData]; 
  3. In your table view cell, replace the image view with a PFImageView , because it can take care of fetching the image data for you (and other useful stuff like cacheing it). Your cellForRowAtIndexPath: will then look like this...

     // bookImageLabel must be a PFImageView // remember, we put the PFFile for each object into the _bookImageData array cell.bookImageLabel.file = _bookImageData[indexPath.row]; [cell.bookImageLabel loadInBackground]; 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM