Application Termination because of NSRangeException (NSMutableArray) - ios

I'm trying to retrieve uploaded thumbnailPhotos from Parse to display them in UITableViewCells, but I get an exception thrown in everytime. The error code is as follows: "Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'"
This is my code:
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"Events"];
[query orderByDescending:#"date"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
} else {
self.events = (NSMutableArray *) objects;
[self.tableView reloadData];
for (PFObject *event in self.events) {
NSInteger index = [self.events indexOfObject:event];
PFFile *imageFile = [event objectForKey:#"thumbnailImage"];
[imageFile getDataInBackgroundWithBlock:^(NSData *result, NSError *error) {
if (error) {
//Handle Error
} else {
UIImage *image = [UIImage imageWithData:result];
if (self.thumbnailPhotos == nil) {
self.thumbnailPhotos = [NSMutableArray array];
self.thumbnailPhotos[index] = image;
} else {
self.thumbnailPhotos[index] = image;
}
[self.tableView reloadData];
}
}];
}
}
}];
}
CellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *reuseIdentifier = #"Cell";
EventsTableViewCell *cell = (EventsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath];
PFObject *event = [self.events objectAtIndex:indexPath.row];
NSDate *date = [event objectForKey:#"date"];
NSString *dateString = [self.dateFormat stringFromDate:date];
NSString *timeString = [self.timeFormat stringFromDate:date];
NSLog(#"IndexPath.row = %ld", (long)indexPath.row);
if ([self.thumbnailPhotos objectAtIndex:indexPath.row] != nil) {
cell.imageView.image = self.thumbnailPhotos[indexPath.row];
} else {
NSLog(#"Nil, Application will crash!");
}
cell.eventNameLabel.text = [event objectForKey:#"title"];
cell.dateLabel.text = dateString;
cell.timeLabel.text = timeString;
[cell.timeLabel sizeToFit];
return cell;
}`
I had to add the index value of self.events because the thumbnailPhotos were downloaded in different speed, so my Cells always showed the wrong photo for the wrong event.
I hope this was enough details to figure the problem out.

Application is crashing because thumbnailPhotos doesn't have any object at index for assignment. Please use following code.
Updated Code which will support Dictionary to hold thumbnail images
/*
Define events as NSMutableArray which holds all events
Define thumbnailPhotos as NSMutableDictionary which holds thumbnail image for index as key
*/
//Create a weak Reference of self for accessing self within block
__weak __typeof(self)weakSelf = self;
PFQuery *query = [PFQuery queryWithClassName:#"Events"];
[query orderByDescending:#"date"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
} else {
//Create a strong reference for updating the UI
__strong __typeof(weakSelf)strongSelf = weakSelf;
//Assign the events to instance object
strongSelf.events = [NSMutableArray arrayWithArray:objects];
//Alloced thumbnail dictionary
strongSelf.thumbnailPhotos = [NSMutableDictionary dictionary];
//Reload tableView so that data will be visible
[strongSelf.tableView reloadData];
for (PFObject *event in strongSelf.events) {
//Define index as block type because we have to use this instance within block
__block NSInteger index = [strongSelf.events indexOfObject:event];
PFFile *imageFile = [event objectForKey:#"thumbnailImage"];
[imageFile getDataInBackgroundWithBlock:^(NSData *result, NSError *error) {
if (error) {
//Handle Error
} else {
UIImage *image = [UIImage imageWithData:result];
//Set the image against index
[strongSelf.thumbnailPhotos setObject:#"" forKey:#(index)];
//Reload only cell for which image is just downloaded
[strongSelf.tableView reloadRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:index inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}];
}
}
}];
Updated:
Modify your cellForRowAtIndexPath as below
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *reuseIdentifier = #"Cell";
EventsTableViewCell *cell = (EventsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath];
PFObject *event = [self.events objectAtIndex:indexPath.row];
NSDate *date = [event objectForKey:#"date"];
NSString *dateString = [self.dateFormat stringFromDate:date];
NSString *timeString = [self.timeFormat stringFromDate:date];
NSLog(#"IndexPath.row = %ld", (long)indexPath.row);
if ([self.thumbnailPhotos valueForKey:#(indexPath.row)]) {
cell.imageView.image = [self.thumbnailPhotos valueForKey:#(indexPath.row)];
} else {
NSLog(#"Nil, Application will crash!");
}
cell.eventNameLabel.text = [event objectForKey:#"title"];
cell.dateLabel.text = dateString;
cell.timeLabel.text = timeString;
[cell.timeLabel sizeToFit];
return cell;
}
In this implementation thumbnail Image is getting saved in to dictionary and second reload of tableView is per cell basis instead of reloading complete tableView for single thumbnail download.

Related

Uneven data loading to UITableViewController from Parse when not using PFQueryTableView

I'm using UITableViewController for displaying data from Parse. It runs perfectly on my Xcode Simulator as i think there's no latency in network. But whenever i'm uploading the code to AppStore for Testing. The very first time i run the app it has to load a couple of restaurant's from Parse and display in UITableViewController. Upon clicking a row the first rows data is being loaded into the 3rd row and 4th row data loading in 6th row data irregularly. Why is the data being loaded very unevenly ? Here's my
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellIdentifier = #"restaurantIdentifier";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
PFObject *tempObject = [self.objectArray objectAtIndex:indexPath.row];
PFFile *imageFile = [tempObject objectForKey:#"RestaurantIcon"];
PFImageView *imageView = [[PFImageView alloc] init];
imageView.file = imageFile;
[imageView loadInBackground:^(UIImage *img,NSError *error){
if(!error){
cell.imageCell.image = imageView.image;
}
}];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.layer.masksToBounds = YES;
cell.imageView.layer.cornerRadius = 4;
cell.imageView.frame = self.view.bounds;
cell.cellLabel.text = [tempObject objectForKey:#"RestaurantName"];
[self.hotelNamesArray addObject:[tempObject objectForKey:#"RestaurantName"]];
cell.cellLabel.lineBreakMode = NSLineBreakByWordWrapping;
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
_restaurantName = [self.hotelNamesArray objectAtIndex:indexPath.row];
self.restaurantMenuNameArray = [[NSMutableArray alloc] init];
PFQuery *query = [PFQuery queryWithClassName:[self.hotelNamesArray objectAtIndex:indexPath.row]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *obj in objects) {
if (![_restaurantMenuNameArray containsObject:[obj objectForKey:#"RestaurantMenuName"]]) {
NSLog(#"restaurantmenunames are %#",[obj objectForKey:#"RestaurantMenuName"]);
if ([obj objectForKey:#"RestaurantMenuName"] ==nil) {
[self performSegueWithIdentifier:#"restaurantDetail" sender:self];
return;
}else {
[_restaurantMenuNameArray addObject: [obj objectForKey:#"RestaurantMenuName"]];
}
}
}
}else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
[self.tableView reloadData];
NSLog(#"restaurantMenuNames is %#",_restaurantMenuNameArray);
[self performSegueWithIdentifier:#"restaurantDetail" sender:self];
}];
}
Thanks in advance.
If you mean the images get in the wrong cell, you have to consider that cells are recycled when you scroll, and that if the image loading takes a bit too long, you may get the result after the cell has been reused.
You need to check that the cell is still for the item/row you want (you could store the row in the cell's tag and check it before setting the image in the completion handler, for instance).
If it's other data that is mixed up, then you'll need to show us the code that loads that data.

Custom UICollectionViewCell not loading

I'm using a storyboard and my custom UICollectionViewCell is not appearing. I played around with it for a few hours and have googled a ton of different solutions but none worked. Just to clarify, the data exists, and the UICollectionView is appearing, but the cell is not. Here is my code. Any suggestions would be appreciated!
- (NSInteger)collectionView:(UICollectionView *)mutualFriendsView numberOfItemsInSection:(NSInteger)section {
return [self.resultsDictionary count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)mutualFriendsView
cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"PCRRequesterMutualFriendsCollectionViewCell";
PCRRequesterMutualFriendsCollectionViewCell *cell = [self.mutualFriendsView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
NSArray *idArray = [self.resultsDictionary objectForKey:#"id"];
NSArray *nameArray = [self.resultsDictionary objectForKey:#"name"];
cell.profileName.text = [nameArray objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor redColor];
return cell;
}
- (void)collectionView:(UICollectionView *)mutualFriendsView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cell #%d was selected", indexPath.row);
}
- (BOOL)shouldAutorotate {
[mutualFriendsView.collectionViewLayout invalidateLayout];
BOOL retVal = YES;
return retVal;
}
EDIT Here is my viewDidLoad
self.mutualFriendsView.dataSource = self;
self.mutualFriendsView.delegate = self;
self.mutualFriendsView.pagingEnabled = YES;
// [self.mutualFriendsView registerClass:[PCRMutualFriendsCollectionViewCell class] forCellWithReuseIdentifier:#"PCRMutualFriendsCollectionViewCell"];
Edit I think I figured out the problem. I don't think the dictionary is being populated after the completion block finishes. Any suggestions for saving the value of the dictionary from the block to be used outside of it?
__block NSMutableDictionary *mutualFriends = nil;
__block NSNumber *total;
NSString *u = [NSString stringWithFormat:#"%#",self.details[#"Requester"][#"profile"][#"facebookId"]];
/* make the API call */
[FBRequestConnection startWithGraphPath:(#"/%#", u)
parameters:params
HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
/* handle the result */
if (!error){
NSLog(#"RESULT OF FB %#", result);
if (result == nil){
NSLog(#"No shared friends");
} else {
total = result[#"context"][#"mutual_friends"][#"summary"][#"total_count"];
NSLog(#"TOTAL FRIENDS %#", total);
for(int i=0;i<[result[#"context"][#"mutual_friends"][#"data"] count];i++)
{
mutualFriends = result[#"context"][#"mutual_friends"][#"data"][i];
NSLog(#"FRIENDDATA %#", mutualFriends);
}
}
} else {
NSLog(#"ERROR %#", error);
}
}];
self.resultsDictionary = mutualFriends;
self.number = total;
NSLog(#"NUMBER %#", self.number);
NSLog(#"RESULTS DICTIONARY %#", self.resultsDictionary);
NSString *friends = [NSString stringWithFormat:#"You have %# friends in common including:", self.number];
After this code:
for(int i=0;i<[result[#"context"][#"mutual_friends"][#"data"] count];i++)
{
mutualFriends = result[#"context"][#"mutual_friends"][#"data"][i];
NSLog(#"FRIENDDATA %#", mutualFriends);
}
// add
self.resultsDictionary = mutualFriends;
mutualFriendsView.reloadData();
All within that completion block. So when FB finally does return and you've accumulated all the mutualFriends, then you tell the collectionView to reload.

UITableViewController [__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array' with PFTask thenCallBackOnMainThreadAsync:]

I am purposely creating a empty Array to not display anything on the UITablewView.
However, it gives me that error.
To debug, I even created an empty UITableViewController and refer storyboard file to this. However, it is giving me the same error.
I just tried and connect it with an empty UIViewController, it is giving me the same objectAtIndex error.
So I doubt it is the problem with the what I am indexing for cells.
When I run, the screen is shown but it throws the error and it freezes.
The declaration of the newsList is:
#property (strong, nonatomic)NSArray *newsList
This is what I have for the UITableViewController.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.currentUser = appDelegate.currentUser;
NSString *addNewsFeed = #"_NewsFeed";
if (self.currentUser)
{
if (appDelegate.selectedGroup == nil)
{
self.newsList = nil;
}
else
{
NSLog(#"SELECTED GROUP EXIST");
NSString *currentNewsFeed = [appDelegate.selectedGroup[#"name"] stringByAppendingString:addNewsFeed];
PFQuery *query = [PFQuery queryWithClassName:currentNewsFeed];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error)
{
NSLog(#"Error: %#, %#", error, [error userInfo]);
}
else
{
self.newsList = objects;
[self.tableView reloadData];
}
}];
}
}
else
{
NSLog(#"%#", appDelegate.currentUser);
[self performSegueWithIdentifier:#"loginView" sender:self];
}
NSLog(#"ZXCVZCVZ: %#", self.newsList);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (appDelegate.selectedGroup == nil)
{
NSLog(#"NO CELL HERE");
return 0;
}
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (appDelegate.selectedGroup == nil)
{
NSLog(#"NO CELL");
return 0;
}
return [self.newsList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"NO LIST FOUND");
static NSString *CellIdentifier = #"News";
NSLog(#"DSFSDFSDFSFS");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFObject *item = [self.newsList objectAtIndex:indexPath.row];
cell.textLabel.text = item[#"title"];
cell.detailTextLabel.text = item[#"news"];
return cell;
}
you need to allocate the memory for array as below
self.newsList=[[NSMutableArray alloc]init];//At viewWIllAppear
Without alloc the self.newsList you cannot able to store any records in it...
Hope it fixes...

findObjectsInBackgroundWithBlock shows no results

I am trying to search my objects on parse.com using a uisearchbar and performing 'findObjectsInBackgroundWithBlock'. I am getting the correct results in my output but they are not showing up in my table.
I was previously doing this without blocks, my code worked, it got the correct results but moved very slowly and I was getting a warning, "Warning: A long-running Parse operation is being executed on the main thread"
I had previously been using the code:
- (void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName: #"Items"];
[query whereKeyExists:#"itemName"];
[query whereKeyExists:#"itemDescription"];
[query whereKey:#"tags" containsString:searchTerm];
NSArray *results = [query findObjects];
NSLog(#"%#", results);
NSLog(#"%u", results.count);
[self.searchResults addObjectsFromArray:results];
}
So now I am trying findObjectsInBackgroundWithBlock instead, I have not worked with blocks before so this is where I need help, here is my new code:
- (void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName: #"Items"];
[query whereKey:#"tags" containsString:searchTerm];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
NSLog(#"%#", objects);
NSLog(#"%u", objects.count);
[self.searchResults addObjectsFromArray:objects];}];
Here is some more of my code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
return self.objects.count;
} else {
return self.searchResults.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
NSString *uniqueIdentifier = #"cell";
HomeCell *cell = nil;
cell = (HomeCell *) [self.tableView dequeueReusableCellWithIdentifier:uniqueIdentifier];
if (!cell) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"HomeCell" owner:nil options:nil];
for (id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[HomeCell class]])
{
cell = (HomeCell *)currentObject;
break;
}
}
}
if (tableView != self.searchDisplayController.searchResultsTableView) {
NSString *itemName = [object objectForKey:#"itemName"];
NSString *itemDescription = [object objectForKey:#"itemDescription"];
//cell.textLabel.text = last;
cell.cellTitleLabel.text = itemName;
cell.descriptionLabel.text = itemDescription;
cell.priceLabel.text = [object objectForKey:#"price"];
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = cell.imageFile;
thumbnailImageView.image = [UIImage imageNamed:#"Facebook #2x.png"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
}
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]) {
PFObject *obj2 = [self.searchResults objectAtIndex:indexPath.row];
PFQuery *query = [PFQuery queryWithClassName:#"Items"];
PFObject *searchedItems = [query getObjectWithId:obj2.objectId];
NSString *itemName = [searchedItems objectForKey:#"itemName"];
NSString *itemDescription = [searchedItems objectForKey:#"itemDescription"];
cell.cellTitleLabel.text = itemName;
cell.descriptionLabel.text = itemDescription;
cell.priceLabel.text = [searchedItems objectForKey:#"itemName"];
PFFile *thumbnail = [searchedItems objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = cell.imageFile;
thumbnailImageView.image = [UIImage imageNamed:#"Facebook #2x.png"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
}
return cell;
Any help would be greatly appreciated,
cheers
In order to update the table view, you need to call the reloadData: method once you have added the new search results. Make sure that you call this method within the block that you provide to findObjectsInBackgroundWithBlock: because this block of code will be run on a separate thread. This causes the method to return instantly, and code after this method will then run before the block has actually executed. Your find objects code within filterResults: should look something like this:
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// This block is called from a background thread once the query has been executed
NSLog(#"%#", objects);
NSLog(#"%u", objects.count);
[self.searchResults addObjectsFromArray:objects];
// Refresh the table view on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
[self.searchDisplayController.searchResultsTableView reloadData];
});
}];
Differentiate from your search table view and your regular tableview when you create the cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
if (tableView = self.tableView) {
//Configure your cell normally
}
else {
//Configure your cells using
cell.someAttribute = self.searchResults[indexPath.row].someAttribute;
}

Parse query in ViewDidLoad for UICollectionViewController

I'm trying to adapt the use of a UICollectionViewController I'm populating with an Array of local images to get the images from Parse.
So far it's pretty straightforward. My NSArray is filled with the same local image many times:
testImages = [NSArray arrayWithObjects: #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", #"thumbnail.jpg", nil];
On the collectionView:cellForItemAtIndexPath: I do set up my cell (from Storyboard):
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// Set up cell identifier that matches the Storyboard cell name
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
// Configure the cell to show photo thumbnail
UIImageView *testImageView = (UIImageView *)[cell viewWithTag:100];
testImageView.image = [UIImage imageNamed:[testImages objectAtIndex:indexPath.row]];
return cell;
}
This is working and looks like this:
What I'm trying to do is to replace the locally created array from pictures that I get out of my Photo Class in Parse.
I'm trying to do this on the viewDidLoad method:
PFQuery *query = [PFQuery queryWithClassName:#"Photo"];
PFUser *user = [PFUser currentUser];
[query whereKey:#"user" equalTo:user];
[query orderByAscending:#"createdAt"];
[query setCachePolicy:kPFCachePolicyNetworkOnly];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %d photos.", objects.count);
testImages = [NSMutableArray arrayWithArray:objects];
NSLog(#"# Images: %d", [testImages count]);
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"Object Name: %#", object.objectId);
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
The thing is that I'm getting an empty array every time. I'm guessing that since this is getting executed on the block in the background once the collectionView:numberOfItemsInSection: asks for the count of elements on the "testImages" array I always get 0 elements.
When the UICollectionViewController wants to use the information from the array to fill in the cells there's nothing there.
I don't know if I'm placing my code in the wrong place or if I'm using the wrong query.
Can you get my error here?
Any feedback would be greatly appreciated.
finally I got something working. #gg13's feedback has been key to solve the empty array problem.
I'll leave the solution here just in case it helps anyone else some other time.
I put my query on a new method:
- (void)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:#"Photo"];
PFUser *user = [PFUser currentUser];
[query whereKey:#"user" equalTo:user];
[query orderByAscending:#"createdAt"];
[query setCachePolicy:kPFCachePolicyNetworkOnly];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %d photos.", objects.count);
[self.collectionView reloadData];
gridImages = [[NSMutableArray alloc] initWithCapacity:objects.count];
// Do something with the found objects
for (PFObject *object in objects) {
PFFile *thumbnail = [object objectForKey:#"thumbnail"];
[thumbnail getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
// Now that the data is fetched, update the cell's image property with thumbnail
NSLog(#"Fetching image..");
[gridImages addObject:[UIImage imageWithData:data]];
NSLog(#"Size of the gridImages array: %d", [gridImages count]);
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
That I'm calling on viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self queryForTable];
}
Then I changed my collectionView:cellForItemAtIndexPath: method to this:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// Set up cell identifier that matches the Storyboard cell name
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
// Configure the cell to show photo thumbnail
UIImageView *imageView = (UIImageView *)[cell viewWithTag:100];
//NSLog(#"testImages: %#", [testImages objectAtIndex:indexPath.row]);
imageView.image = [UIImage imageNamed:#"placeholder.jpg"];
imageView.image = [gridImages objectAtIndex:indexPath.row];
return cell;
}
And so far it's working. The app is getting the images from Parse and it looks like this:
I still have to test a few things and specially the scenario with huge amount of images (including a progress indicator or something) but at least to get this already is a good thing.
I'm sure Parse will make their own UICollectionViewController sooner or later as they did with the UITableViewController and things will improve even more.
As said before, thanks for the feedback, I'm leaving this here just in case someone else comes into the same problem and of course open to feedback and suggestions.
Cheers,

Resources