Reputation: 900
Currently, I'm trying to implement my images from a parse query in a UICollectionView. Initially I tied doing this:
Here is my viewDidLoad
:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"View Did Load");
// Do any additional setup after loading the view, typically from a nib.
PFQuery *query = [PFQuery queryWithClassName:@"SwapPost"];
self.dataArray = [query findObjects];
[self setupCollectionView];
}
and here is my cellForItemAtIndexPath
:
-(CMFGalleryCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"Row: %ld",(long)indexPath.row);
CMFGalleryCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
NSString *imageName = @"Picture";
if(imageName == nil){
NSLog(@"imageName is nil");
}
[cell setImageName:imageName];
PFFile *file = [[self.dataArray objectAtIndex:indexPath.row] objectForKey:@"image"];
NSLog(@"filename = %@",[file name]);
cell.imageView.file = file;
[cell.imageView loadInBackground];
return cell;
}
but for some reason, even though some of my debugging code outputted that there were 19 objects retrieved, only one image was displaying when there should have been 19 (each object had a PFFile image)
Then, I changed the latter method to this:
-(CMFGalleryCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"Row: %ld",(long)indexPath.row);
CMFGalleryCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
PFQuery *newQuery =[PFQuery queryWithClassName:@"SwapPost"];
NSArray *newArray = [newQuery findObjects];
NSLog(@"%@",[[newArray objectAtIndex:indexPath.row] objectId]);
NSString *imageName = @"Picture";
if(imageName == nil){
NSLog(@"imageName is nil");
}
[cell setImageName:imageName];
PFFile *file = [[newArray objectAtIndex:indexPath.row] objectForKey:@"image"];
NSLog(@"filename = %@",[file name]);
cell.imageView.file = file;
[cell.imageView loadInBackground];
return cell;
}
And this displayed all the 19 images I wanted..however I'm implementing a horizontal image scroller, one image at a time (so one cell at a time) and that means every time the user is scrolling the query is calling findObjects
over and over which can get quite cumbersome on the network and make the app lag. Is there anyway to fix it so that I only have to call findObjects
once and then I can smoothly display all 19 images?
Upvotes: 0
Views: 511
Reputation: 11598
I think you have a misunderstanding of how the UICollectionView
works. Once you have obtained the data you will use for your data source (UICollectionViewDataSource
Protocol), you do not reload that unless the backing data has changed.
Here's a sample of what I think your code should look like, based on what you have stated. Please note: I couldn't figure out what do to with imageName
, since you always assigned it immediately upon creation and then test it for nil
, which will never be true based on your code. Therefore, I deleted that bit.
- (void)viewDidLoad {
[super viewDidLoad];
[self runQuery];
}
- (void)runQuery {
PFQuery *query = [PFQuery queryWithClassName:@"SwapPost"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// You obviously need better error handling in here...
self.dataArray = objects;
[self.collectionView reloadData];
}
];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
// This is an assumption
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.dataArray.count;
}
- (CMFGalleryCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CMFGalleryCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
PFObject *post = self.dataArray[indexPath.row];
PFFile *file = post[@"image"];
cell.imageView.file = file;
[cell.imageView loadInBackground];
return cell;
}
Now, this is not complete code. It will work, but it's not optimized and it doesn't have error handling in case you don't get anything back (or get an error) from Parse. Also, depending on how long the query takes, your UI will show nothing to indicate to the user that progress is being made. I generally use an instance of MBProgressHUD
to block the UI and indicate that the query is being made. With those caveats aside, this should get you started.
Upvotes: 2