Reputation: 2051
I have a UITableViewController
that I use to display the names of a list of local Business objects. I have used this UITableViewController
previously to read information from a .csv file and this was all working and displaying the Business names in my UITableViewController
perfectly.
However, I have recently moved all this information to Parse.com and I am now trying to read and display the information from Parse.com in my current UITableViewController
.
I am trying to refactor the code rather than use Parse.com's tutorials here: https://www.parse.com/docs/ios_guide#ui-tables/iOS
In my viewDidLoad
method, I call my own method [self initializeContent]
which does the PFQuery
to retrieve a list of objects that fit a certain criteria and then save the objects in an NSMutableArray
.
This executes fine and I can see the Business objects are being retrieved through my NSLogs
in my [self initializeContent]
method and saved to a NSMutableArray
(dataArray).
However, when stepping through the code, my dataArray
is 0 in the numberOfSectionsInTableView
method. Therefore I dont see the Business names displayed in the UITableViewController
.
Does the numberOfSectionsInTableView
get executed before the viewDidLoad
method perhaps, meaning that my dataArray
will always be 0?
I have stepped through the code but cant figure out where my issue is.
Below is my code - I have included as much as I can to help identify where my problem is.
BusinessDetailTableViewController.h
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
@interface BusinessDetailTableViewController : UITableViewController
@property (nonatomic, strong) NSMutableArray *dataArray;
@property (nonatomic, strong) NSMutableArray *defaultBusinessArrayMutable;
@property (nonatomic, assign) int tagNumber;
@property (nonatomic, strong) NSString *className;
@end
BusinessDetailTableViewController.m
#import "BusinessDetailTableViewController.h"
#import "BusinessDetailContent.h"
#import "DetailViewController.h"
#import <Parse/Parse.h>
@interface BusinessDetailTableViewController ()
@end
@implementation BusinessDetailTableViewController
@synthesize dataArray;
@synthesize defaultBusinessArrayMutable;
@synthesize tagNumber;
@synthesize className;
- (void)viewDidLoad
{
[super viewDidLoad];
[self initializeArrays];
[self initializeContent];
}
- (void) initializeArrays
{
dataArray = [[NSMutableArray alloc] init];
defaultBusinessArrayMutable = [[NSMutableArray alloc] init];
}
- (void) initializeContent
{
NSLog(@"Class Name: %@", className); // Shows the correct className
[self queryParse:className];
}
- (void) queryParse:(NSString *) className
{
PFQuery *query = [PFQuery queryWithClassName:self.className];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (!error)
{
NSLog(@"Successfully Retrieved %d Objects.", (int)objects.count); // Shows how many objects are retrieved
for (PFObject *object in objects)
{
BusinessDetailContent *businessDetailContent = [[BusinessDetailContent alloc] init];
businessDetailContent.no = object[@"ID"];
businessDetailContent.companyName = object[@"Company_Name"];
businessDetailContent.address = object[@"Address"];
businessDetailContent.tel = object[@"Tel"];
businessDetailContent.email = object[@"Email"];
businessDetailContent.website = object[@"Website"];
businessDetailContent.details = object[@"Details"];
businessDetailContent.imageName = object[@"Image_ID"];
// The information here is retrieved correctly
NSLog(@"BUSINESS DETAIL CONTENT - ID: %@, Company Name: %@, Address: %@, Tel: %@, Email: %@, Website: %@, Details: %@, Image_Name: %@",
businessDetailContent.no, businessDetailContent.companyName, businessDetailContent.address, businessDetailContent.tel,
businessDetailContent.email, businessDetailContent.website, businessDetailContent.details,
businessDetailContent.imageName);
[defaultBusinessArrayMutable addObject:businessDetailContent];
NSString *strFromInt = [NSString stringWithFormat:@"%d", tagNumber];
if (!([strFromInt isEqualToString:@"3"] || [strFromInt isEqualToString:@"10"]))
{
[dataArray addObject:defaultBusinessArrayMutable];
NSLog(@"Default Business Array Mutable Count: %i", (int)dataArray.count);
}
}
}
}
else
{
NSLog(@"Error retrieving objects: %@ %@", error, [error userInfo]);
}
}];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@" cellForRowAtIndexPath "); // This is not executed
static NSString *CellIdentifier = @"Cell";
NSLog(@"Cell Identifier: %@", CellIdentifier);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell
NSArray *cellArray = [dataArray objectAtIndex:indexPath.section];
BusinessDetailContent *businessDetailContent = [cellArray objectAtIndex:indexPath.row];
cell.textLabel.text = businessDetailContent.companyName;
NSLog(@"Cell Textlabel Text: %@", cell.textLabel.text);
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@" didSelectRowAtIndexPath ");
[self performSegueWithIdentifier:@"businessDetailSegue" sender:self];
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(@"numberOfRowsInSection returning: %d", (int)[dataArray count]);
return [dataArray count]; // dataArray = 0
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSMutableArray *array = [dataArray objectAtIndex:section];
return [array count];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(@"PrepareForSegue: %@", segue.identifier);
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
if ([segue.identifier isEqualToString:@"businessDetailSegue"] && indexPath)
{
NSArray *selectedRowArray = [dataArray objectAtIndex:indexPath.section];
BusinessDetailContent *selectedContent = [selectedRowArray objectAtIndex:indexPath.row];
DetailViewController *detailController = segue.destinationViewController;
detailController.businessDetailContent = selectedContent;
}
}a
@end
EDIT: I have added [self.tableView reloadData]; to the end of my findObjectsInBackgroundWithBlock method as many have suggested and now I am getting to the numberOfSectionsInTableView method, but the dataArray is still 0. And it looks as though my code is executing twice as can be seen by the Console print?
For my dataArray in my queryParse method it returns 18 objects - but there should be only 9. From the Console print Hotel Array Count starts at 2 and increments by 2 each time after that.
And my numberOfRowsInSection is now getting executed twice, but before the Parse.com query.
I am totally stuck with this.
Upvotes: 2
Views: 452
Reputation: 2514
@Hans Moolman, yes you are correct, You just need to call the reload method of table view after your parsing is done. i .e.
- (NSMutableArray *) queryParse:(NSString *) className
{
PFQuery *query = [PFQuery queryWithClassName:self.className];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (!error)
{
NSLog(@"Successfully Retrieved %d Objects.", (int)objects.count); // Shows how many objects are retrieved
for (PFObject *object in objects)
{
BusinessDetailContent *businessDetailContent = [[BusinessDetailContent alloc] init];
businessDetailContent.no = object[@"ID"];
businessDetailContent.companyName = object[@"Company_Name"];
businessDetailContent.address = object[@"Address"];
businessDetailContent.tel = object[@"Tel"];
businessDetailContent.email = object[@"Email"];
businessDetailContent.website = object[@"Website"];
businessDetailContent.details = object[@"Details"];
businessDetailContent.imageName = object[@"Image_ID"];
// The information here is retrieved correctly
NSLog(@"BUSINESS DETAIL CONTENT - ID: %@, Company Name: %@, Address: %@, Tel: %@, Email: %@, Website: %@, Details: %@, Image_Name: %@",
businessDetailContent.no, businessDetailContent.companyName, businessDetailContent.address, businessDetailContent.tel,
businessDetailContent.email, businessDetailContent.website, businessDetailContent.details,
businessDetailContent.imageName);
[defaultBusinessArrayMutable addObject:businessDetailContent];
NSString *strFromInt = [NSString stringWithFormat:@"%d", tagNumber];
if (!([strFromInt isEqualToString:@"3"] || [strFromInt isEqualToString:@"10"]))
{
[dataArray addObject:defaultBusinessArrayMutable];
NSLog(@"Default Business Array Mutable Count: %i", (int)dataArray.count);
}
}
}
}
else
{
NSLog(@"Error retrieving objects: %@ %@", error, [error userInfo]);
}
}];
// This line to be added
[self.tableView reloadData];
}
If still problems exists, do let me know. Thanks.
Upvotes: 2
Reputation: 101
Hi first you set bool value default to false i mean viewdidload. By parsing at didfinishloading function set bool to true
In numberofrowsinsection
if(!bool)
{
///just hide the tableview
}
else
{
[data count];
}
Upvotes: 1
Reputation: 119031
The call to parse.com returns data asynchronously, so the view will have finished loading and done its check for row count before the data is received. When the data is received you need to tell the table view to check the row count again and refresh - this is what you're missing.
[self.tableView reloadData];
and it should go in queryParse:
, at the end of the completion block of findObjectsInBackgroundWithBlock:
.
Upvotes: 1