cell imageView in UITableView doesn't appear until selected - ios

Here is a video of the problem: http://youtu.be/Jid0PO2HgcU
I have a problem when trying to set the image for the [cell imageView] in a UITableView from the asset library.
The image is loaded but it doesn't appear in the cell until I touch (select) that cell. Here is my code that sets the imageView of the cell:
//Start loading the image using the image path
NSString *path = [occasion imagePath];
if (path != nil && [path hasPrefix:#"ass"])
{
NSLog(#"photo loaded from assets library");
//testing ALAssestLibrary
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryAssetForURLResultBlock resultsBlock = ^(ALAsset *asset)
{
ALAssetRepresentation *representation = [asset defaultRepresentation];
CGImageRef imageRef = [representation fullResolutionImage];
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
[[cell imageView] setImage:[image imageByScalingAndCroppingForSize:CGSizeMake(36.0, 42.0)]];
[image release];
};
ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error){
NSLog(#"FAILED! due to error in domain %# with error code %d", error.domain, error.code);
// This sample will abort since a shipping product MUST do something besides logging a
// message. A real app needs to inform the user appropriately.
abort();
};
//Convert path to an NSUrl
NSURL *url = [NSURL URLWithString:path];
// Get the asset for the asset URL to create a screen image.
[assetsLibrary assetForURL:url resultBlock:resultsBlock failureBlock:failureBlock];
// Release the assets library now that we are done with it.
[assetsLibrary release];
}
The above code is part of the:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
Any ideas?

I think in this case you're using a iOS defined UITableViewCell (and not a custom one), that is one of those cells that you get from "initWithStyle:reuseIdentifier:". Now these cells are internally built in such way that if you don't assign some content immediately the corresponding subview will not be added in the cell's contentView hierarchy. This kind of behavior is typical of complex custom views, where the final cell layout can be determined only when all its subviews have their content fully specified. (E.g. you have two labels, let's say label A and label B, label A is multirow and you want to add label-B immediately below label-A, then you can place label-B correctly only once you have the label-A content and you calculate its height.). So I suppose the built-in iOS table cells are done in the same way and the subviews hierarchy is built at the "layoutSubviews" stage.
In your case you create the cell but defer the time the image is provided. But at this point the layoutSubviews has been called yet and without any image the corresponding imageView is not even allocated and added in the contentView hierarchy!
So, according to me, the solution for you is just to assign immediately a "placeholder" for your asset (the placeholder can be a transparent image of course) which will guarantee you of the internal UIImageView creation. Be careful with the image size, it should be close to the expected image size, for the same reason explained above. As soon as your finish block is called the image view should be already there and the image will appear.
The reason why when you tap on the cell the image appears, is due to the fact that this operation calls the layoutSubviews again. In this case the whole code is probably re-executed and as you already called "setImage:" before then the internal "image" property is set and the contentView hierarchy will be rebuilt with the new image.
Another possible solution to your problem is of course to use a "custom" UITableViewCell (e.g. loaded from a Nib). In such case all your subviews will be loaded and you will simply access to the UIImageView using his tag (read apple docs to know more about this useful technique to create table view cells from a Nib file).

you need to layout cell after image set
just like
[cell setNeedsLayout];

I scratched my head for so long and finally figured it out.
My mistake was that I was setting image in cell.imageView when I should be setting my actual outlet cell.eventImageView. It was messing with the generic imageview provided in UITableViewCell. Hope it helps somebody.

This is my way how i solved these problem, i know is not the best but that work :)
UIImage *thumbnailImage = ...
dispatch_async(dispatch_get_main_queue(), ^{
[cell.imageView setImage:thumbnailImage];
UITableViewCellSelectionStyle selectionStyle = cell.selectionStyle;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[cell setSelected:YES];
[cell setSelected:NO];
cell.selectionStyle = selectionStyle;
});

In my case I was setting up a prototype cell through a Storyboard, but was accidentally using the dequeueCellWithIdentifier:forIndexPath method instead of dequeueCellWithIdentifier:.
The first method is only to be used when appropriating cells to a tableview through the programmatic UITableView registerClass:forReuseIdentifier: or registerNib:forReuseIdentifier methods.

I was having a similar problem. I had registered the default UITableViewCell class instead of my custom class.
I had this:
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: visibilityCellIdentifier)
but I should have had this:
tableView.registerClass(VisibilityCell.self, forCellReuseIdentifier: visibilityCellIdentifier)
The cell creation all looked to be working as I stepped through the debugger, but nothing showed up until I selected each row.

I get same issue when i use this code:
cell = [tableView dequeueReusableCellWithIdentifier:kCellSection1 forIndexPath:indexPath];
if (indexPath.row == 0) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellSection1];
cell.textLabel.text = #"Vote Up for me if it help for you!";
}
But I fix it by replace:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellSection1];
To:
cell = [cell initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellSection1];

Sometime it happens when you are using custom UITableViewCell with labels, images etc but also somewhere you are setting default UILabel of cell. for example
customCell.textLabel.text = #"some text"
To solve this problem, avoid using default label, instead add your own UILabel in your custom cell.

Related

UITableCell AccessoryView: Setting accessoryView equal to UIImageView infinite loop

EDIT: I have figured out the answer on my own but here it is for anyone else who needs it:
UIImageViews cannot be shared so a different instantiation of each UIImageView is required for each visible cell. Now you know.
I have a custom table that has 2 types of cells. One cell is just set to toggle between a normal accessory of type checkmark. Another cell is set to have a custom image as the accessory type. When selected that accessory image changes to its opposite type, showing an "Invited" or "Invite" message.
I've narrowed down the code at fault to the following, found within my tableView:cellForRowAtIndexPath delegate method.
if(indexPath.section == 0){
cell = [tableView dequeueReusableCellWithIdentifier:self.directCellID];
cellValue = [self.contactsUsingApp objectAtIndex:indexPath.row];
cell.imageView.image = [self getContactImage:indexPath.row];
//vvvvvvvvvvvvvvvvv This is the section at fault vvvvvvvvvvvvvvvvv
if([self.selectedContactsUsingApp containsObject:indexPath])
cell.accessoryView = self.invitedStatus;
else
cell.accessoryView = self.notInvitedStatus;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
If I comment out that section I no longer have runaway memory usage (the Simulator showed me that there was some sort of constant allocation going on, it got up passed 1.29Gb after starting from 40Mb) but, obviously, the images no longer show.
If it matters the UIImageViews are initialized as follows:
UIImage *invite = [self imageWithImage:[UIImage imageNamed: #"invite_btn.png"] scaledToSize:CGSizeMake(40, 20)];
UIImage *invited = [self imageWithImage:[UIImage imageNamed: #"invited_btn.png"] scaledToSize:CGSizeMake(40, 20)];
self.notInvitedStatus = [[UIImageView alloc]initWithImage:invite];
self.invitedStatus = [[UIImageView alloc]initWithImage:invited];
(imageWithImage:scale is a function that returns a resized image to the appropriate scale accounting for retina found here: The simplest way to resize an UIImage?)
The same freezing happens when I select one of the cells because my tableView:didSelectRowAtIndexPath method works by the same toggling logic as the initialization method.
Help?
I have figured out the answer on my own but here it is for anyone else who needs it: UIImageViews cannot be shared so a different instantiation of each UIImageView is required for each visible cell. Now you know.

ios 7 - Async Image Download UITableView For Image with Unknown Dimension

I am using XCode 6.3.1 targeting iOS 7.
I am using AFNetworking's UIImageView category to download images with an unknown dimension to UITableViewCell's. Here is a sample image:
The issue I am having is that since the dimensions of the image is unknown, I just use a placeholder image. If the placeholder image has the exact same dimensions, then there is no issue. However, if the dimensions are different, there are issues with spacing in the cell.
If the image is smaller than there will be too much spacing. Here is an example:
I don't know how to refresh the cell after I finish downloading the image so that the spacing is per my Auto Layout Constraints.
If I scroll away from the cell and scroll back, the spacing is fine.
Here is some sample code for the downloading of the image
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Temp
static NSString *Cell = #"CustomListCell";
CustomListCell *cell = (CustomListCell *)[self.tableView dequeueReusableCellWithIdentifier:Cell];
CustomListRow *customListRow = self.customList.rows[indexPath.row];
// Reset the cell
cell.headerImageView.image = nil;
cell.titleLabel.text = #"";
// Download the image, placeholder image is necessary
NSString *topImageURL = #"sample_image";
__weak __typeof(cell)weakCell = cell;
if ([topImageURL isEqualToString:#""] || [topImageURL isEqualToString:#"false"])
{
// Do nothing
} else {
[cell.headerImageView setImageWithName:topImageURL afterManipulation:^UIImage *(UIImage *image) {
// Manipulation
UIImage *newImage = [UIImage expandImage:image toWidth:Constants.screenWidth - 16];
// CustomListCell *updateCell = (CustomListCell *)[tableView cellForRowAtIndexPath:indexPath];
// if (updateCell)
// updateCell.headerImageView.image = newImage;
return newImage;
} placeholderImage:[UIImage expandImage:Constants.placeholderImage toWidth:Constants.screenWidth - 26]];
}
return cell;
}
setImageWithName:afterManipulation:placeholderImage: is a method I made to wrap around AFNetworking's setImageWithURL.... It first checks of the image exists locally before checking two different URL's (absolute and base_url + relative) if the image exists there.
I put the manipulation block in there so that I could call a UIImage category method I created that will scale the image to fit the width of the UITableView (so the only dynamic part is the height).
Here is a list of things I have tried:
Reloading the particular cell
reloading the entire table
[self.tableView beginUpdates] + [self.tableView endUpdates];
Calling [cell setNeedsLayout], or [cell setNeedsDiplay];
setNeedsLayout and setNeedsDisplay didn't do anything once I finished loading the image (I placed it in the afterManipulation block which is called before the image is assigned, and I have also tried placing it after the image is assigned).
Reloading the cell, the table, or beginUpdates causes some really weird behavior to occur. The cells start getting mixed together and some cells have the same picture (which shouldn't happen). I'm not sure what is happening, but my guess is that reloading the cell causes image to download again (or pull it from the cache) which doesn't finish until after another cell is loaded.
Have you thought about playing with the contentMode property of the image view?
A flag used to determine how a view lays out its content when its bounds change.
An issue that I observed while looking at your implementation is that you might get wrong images in the cells. I see you take the cell as a reference when downloading the image. This is wrong, and here is why:
Table view cells get reused so when you scroll the cells that get off screen will be used again to display the information for other rows. By taking a reference to the cell and not the indexpath, if your download takes time, when the completion block is called, that cell may be displaying information for a different row and thus, the image you apply on it may not be the right one.
You should have a look at Apple's example of how to keep consistency while downloading images for every table view cell: https://developer.apple.com/library/ios/samplecode/LazyTableImages/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009394-Intro-DontLinkElementID_2

UIImage within a UITableViewCell is resizing on row selection and on return from pushed view

I'm new to iOS and hope someone can give me some guidance.. I have a custom tableviewcell which has a UIImage within it. When the UITableView loads and cells are created the image loaded remains within the frame of the UIImageView control. When a row selection takes place the image is resized so to fill the height allowed by the cell. Only the row selected is affected at this time. A similar issue arises on return from a child view (which is loaded as a result of pressing a button on the cell).
I've tried placing constraints on the height & width (as well the x, y position within the superview) of the UIImageView, and tried setting the bounds and frame of the UIImageView within the cellForRowAtIndexPath event. None of which seem to have an effect.
Removing all of my attempts at fixing this and getting back to the simplest of code...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *favoriteImageFileName = [[NSString alloc] initWithFormat:#"%#/Folder-Favorite_24px.png", documentDirectory];
NSString *videoPlayImageFileName = [[NSString alloc] initWithFormat:#"%#/Video-4_24px.png", documentDirectory];
NSString *imageInQuestion = [[NSString alloc] initWithFormat:#"%#/T-BoneDish128.png", documentDirectory];
SearchResultsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultsTableViewCell"];
UIImage * favoriteIcon = [[UIImage alloc] initWithData:[[NSData alloc] initWithContentsOfFile:favoriteImageFileName]];
UIImage * videoPlay = [[UIImage alloc] initWithData:[[NSData alloc] initWithContentsOfFile:videoPlayImageFileName]];
UIImage * image = [[UIImage alloc] initWithData:[[NSData alloc] initWithContentsOfFile:imageInQuestion]];
[cell.videoPlayButton setBackgroundImage:videoPlay forState:UIControlStateNormal];
[cell.favoriteImage setImage:favoriteIcon];
[cell.imageView setImage:image];
return cell;
}
I'd appreciate any help offered.
The UITableCell was subclassed to provide access to the custom attributes (image, labels and button). The names of the properties of the new class matched those of the standard template (i.e. image).
However when populating these properties in code only those in the super where being updated. The subclass properties which were the one actually linked to the outlets of labels, and image on the custom cell remained nil.
So when the image was being displayed it was accessing the image in the super and not those subclass and any constraints did not appear to be applied because the image the constraints were applied to was nil and not being displayed. An important point to remember in future is that whenever you create a custom UITableCell never use any of the names of the properties of the super.
As soon as the properties in the subclass were made different to those of the super, those were updated correctly, the image outlet linked to subclass then had an image to display and the constraints got applied as expected.
You don't get a compiler error or warning when you 'override' properties of a super which could be done inadvertently as was in this case. Hope this helps other IOS/Objective C newbies.

Loading images asynchronously, weird problems

There is my question:
i have custom class that parse through an XML and get string i need to use as URL for my strings, now i modified my code as follow:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UILabel *labelText = (UILabel *)[cell viewWithTag:1000];
labelText.text = [[self.listOfPlaceDetails objectAtIndex:indexPath.row] objectForKey:#"name"];
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
NSURL *imageURL = [NSURL URLWithString:[[self.listOfPlaceDetails objectAtIndex:indexPath.row]objectForKey:#"imageCell"]];
NSData *image = [[NSData alloc] initWithContentsOfURL:imageURL];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = [UIImage imageWithData:image];
});
});
return cell;
}
This is pretty straightforward, but, i got unpredictable errors! During scrolling table, images start to chaotically change, sometimes it show 3 or more images and final image is correct one, sometimes final (correct) image does not appear at all. Also, when table is first shown, its actually blank, so i need to scroll it bottom, and then up again to see my images!
In attempt to fix that, i add following code, to determine is my image link correct for that indexPath:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSURL *imageURL = [NSURL URLWithString:[[self.listOfPlaceDetails objectAtIndex:indexPath.row]objectForKey:#"imageCell"]];
NSLog(#"%#", imageURL);
}
And when i tap to any cell, it does show me proper link in console log, but image on cell is one of the image shown before (invalid), and it is not the image for that link. How to fix that weird errors?
Any advice would be appreciated, thank you.
When you dequeue a cell object, most of the time you'll get a reused cell i.e. a cell that has been configured by tableView:cellForRowAtIndexPath: once or more times before.
To visualise what's happening in your case, consider one likely sequence of events for a single cell as you perform a long, quick scroll:
The cell is created and an image load is spun off in the background
The cell is scrolled off screen, so added to the table view's cache, ready for dequeuing. The image loading is not canceled at this point
The cell is dequeued and an image load is spun off in the background
Steps 2 and 3 are repeated a few times
The cell is visible, but the several image loading tasks are now completing and each is updating the cell's imageView with the loaded image. This will indeed look like the images are chaotically changing as each loading operation finishes.
(What's more, with a concurrent queue, there's no guarantee that the image loads will complete in the order that they're started - you may not end up with the correct final image!)
So what do we do about it? Now that we understand the problem, there are lots of different solutions. A very simple solution (that I don't really recommend) is to check that the cell's label text matches the value for that indexPath, when you come to set the image:
if ([labelText.text isEqualToString:[[self.listOfPlaceDetails objectAtIndex:indexPath.row] objectForKey:#"name"]]) {
cell.imageView.image = [UIImage imageWithData:image];
}
Obviously, this assumes that all the place details have unique names.
A better solution might be to create an object that handles the image download, and is something that you can register/unregister cells against to handle download completion. This object could enforce the condition that a cell cannot be waiting for more than one image load. As #Leena pointed out, caching is a good idea and this object could be responsible for that too.
As for the blank images, calling [cell setNeedsLayout] after setting the image should sort that out.
Default property "imageView" will not be added to the cell until its (imageView's) property "image" is nil (you can check cell.imageView.superview will be nil too).
That's why your tableView is blank when it is loaded and all images for cells are also loaded.
So when you scroll it down (or up) cells will be reloaded, their "imageView" will have image data. That is the reason why they are on cell and you can see them.
The other problem is that your images are flashing all the time. It happens because your cells are dequeued.
So, when the image for the first cell is downloaded and setted it will not be shown until you relayout cell's subviews (for example by calling [cell setNeedsLayout];-).
And when you scroll table down, your first cell (with an image now) will be dequeued from "tableView" and will become last cell, and then your first cell will be shown with image that actually belongs to the first row.
At the same time you start downloading image for this (last) row and after it was downloaded you will set it. And this is the monent when flashing happens.

Reuse of UICollectionViewCells during scrolling

I'm having an issue,
I have a simple UICollectionView with a static 200 cells that load images from Flickr.
my CellForItemAtIndexPath looks like this:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"FlickrCell" forIndexPath:indexPath];
cell.backgroundColor = [self generateRandomUIColor];
if(![[cell.subviews objectAtIndex:0] isKindOfClass:[PFImageView class]])
{
NSURL *staticPhotoURL = [self.context photoSourceURLFromDictionary:[self.photos objectAtIndex:indexPath.row] size:OFFlickrSmallSize];
PFImageView *imageView = [[PFImageView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.height, cell.frame.size.width) andImageURL:staticPhotoURL andOwningCell:cell];
[cell addSubview:imageView];
}
return cell;
}
PFImageView is a subclass of UIImageView that loads a Flickr photo URL on a background thread and then updates it's own image on the main thread - this works fine.
The logic is really simple - I create a cell if there isn't one dequeueable.
If the cell (which I'm expecting to be dequeued and already have a PFImageView) doesn't have a PFImageView, I alloc and init an imageView for the cell and add it as a subview of the cell.
Thus I expect if the cell has been dequeued it should already have a PFImageView as a subview and as we should not get into the if statement to create a new imageView and kick off a new photo download request
Instead what I see is that the cells at the top and bottom of the UICollectionView that 'go off screen' momentarily - when they come back on screen they are not being reused and seemingly a new cell is created and the picture refreshed.
1) How can I achieve a static image once the cell has been created (i.e. not refreshing when the cell goes slightly off screen.
2) Why are the cells not being reused?
Many thanks for your time.
John
UICollectionView will reuse cells for maximum efficiency. It does not guarantee any particular reuse or population strategies. Anecdotally, it seems to place and remove cells based on integer power of two regions — e.g. on a non-retina iPad it might divide your scroll area up into regions of 1024x1024 and then populate and depopulate each of those regions as they transition into and out of the visible area. However you should not predicate any expectations on its exact behaviour.
In addition, your use of collection view cells is incorrect. See the documentation. A cell explicitly has at least two subviews — backgroundView and contentView. So if you add a subview it will be at index 2 at the absolute least and, in reality, the index will be undefined. In any case you should add subviews to contentView, not to the cell itself.
The most normal way of doing what you're doing would be to create a custom UICollectionView subclass that inherently has a PFImageView within it.
I see several potential issues:
You are looking specifically at index 0 of the cell for the child class that you are adding. The UICollectionViewCell may have other views as children, so you can't just assume that the only (or first) child is the one you added.
I don't see that you are calling registerClass:forCellWithReuseIdentifier: or registerNib:forCellWithReuseIdentifier:, one of which is required for proper use of dequeue (https://developer.apple.com/library/ios/documentation/uikit/reference/UICollectionViewCell_class/Reference/Reference.html).
You are only setting the URL of the PFImageView in the case that you have to construct the PFImageView. The idea with dequeuing reusable views is that you will only construct a small subset of the views needed, and the UITableView will recycle them as they move offscreen. You need to reset the value for the indexPath that is being requested, even when you don't construct the new content.
If your case is as simple as you describe, you can probably get away with adding your PFImageView to the contentView property of your dequeued UICollectionView.
In your controller:
// solve problem 2
[self.collectionView registerClass:[UICollectionViewCell class] forReuseIdentifer:#"FlickrCell"];
In collectionView:cellForItemAtIndexPath
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"FlickrCell" forIndexPath:indexPath];
cell.backgroundColor = [self generateRandomUIColor];
// solve problem 1 by looking in the contentView for your subview (and looping instead of assuming at 0)
PFImageView *pfImageView = nil;
for (UIView *subview in cell.contentView.subviews)
{
if ([subview isKindOfClass:[PFImageView class]])
{
pfImageView = (PFImageView *)subview;
break;
}
}
NSURL *staticPhotoURL = [self.context photoSourceURLFromDictionary:[self.photos objectAtIndex:indexPath.row] size:OFFlickrSmallSize];
if (pfImageView == nil)
{
// No PFImageView, create one
// note the use of contentView!
pfImageView = [[PFImageView alloc] initWithFrame:CGRectMake(0, 0, cell.contentView.frame.size.height, cell.frame.size.width) andImageURL:staticPhotoURL andOwningCell:cell.contentView];
[cell.contentView addSubview:pfImageView];
}
else
{
// Already have recycled view.
// need to reset the url for the pfImageView. (Problem 3)
// not sure what PFImageView looks like so this is an e.g. I'd probably remove the
// URL loading from the ctr above and instead have a function that loads the
// image. Then, you could do this outside of the if, regardless of whether you had
// to alloc the child view or not.
[pfImageView loadImageWithUrl:staticPhotoURL];
// if you really only have 200 static images, you might consider caching all of them
}
return cell;
For less simple cases (e.g. where I want to visually lay out the cell, or where I have multiple children in the content), I typically customize my UICollectionViewCell's using Interface Builder.
Create a subclass of UICollectionViewCell in the project (In your case, call it PFImageCell).
Add an IBOutlet property to that subclass for the view I want to change in initialization (In your case, a UIImageView).
#property (nonatomic, assign) IBOutlet UIImageView *image;
In Interface Builder, create a prototype cell for the UITableView.
In the properties sheet for that prototype cell, identify the UICollectionViewCell subclass as the class.
Give the prototype cell an identifier (the reuse identifier) in the property sheet.
Add the view child in interface builder to the prototype cell (here, a UIImageView).
Use IB to map the IBOutlet property to the added UIImageView
Then, on dequeue in cellForRowAtIndexPath, cast the dequeued result to the subclass (PFImageCell) and set the value of the IBOutlet property instance. Here, you'd load the proper image for your UIImageView.
I am not sure if the cell is being re-used or not. It may be being reused but the subview may not be there. My suggestion would be to create a PFImageViewCollectionViewCell Class (sub class of UICollectionViewCell) and register it as the CollectionView Cell and try. That's how I do and would do if I need a subview inside a cell.
Try adding a tag on this particular UIImageView
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static int photoViewTag = 54353532;
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"FlickrCell" forIndexPath:indexPath];
cell.backgroundColor = [self generateRandomUIColor];
PFImageView *photoView = [cell.contentView viewWithTag:photoViewTag];
// Create a view
//
if (!photoView) {
photoView = [[PFImageView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.height, cell.frame.size.width) andImageURL:staticPhotoURL andOwningCell:cell];
imageView.tag = photoViewTag;
[cell.contentView addSubview:imageView];
}
// Update the current view
//
else {
NSURL *staticPhotoURL = [self.context photoSourceURLFromDictionary:[self.photos objectAtIndex:indexPath.row] size:OFFlickrSmallSize];
photoView.imageURL = staticPhotoURL;
}
return cell;
}
I would really recommend to create your own UICollectionViewCell subclass though.
EDIT: Also, note that I used the contentView property instead of adding it directly to the cell.

Resources