I would like to start some animation on a UICollectionViewCell when the user taps on a cell. My idea was to select the corresponding cell in didSelectItemAtIndexPath and trigger an animation. However, this doesn't work:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// animate the cell user tapped on
ProductCollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ProductReuseID" forIndexPath:indexPath];
[UIView animateWithDuration:5.0
delay:0
options:(UIViewAnimationOptionAllowUserInteraction)
animations:^{
NSLog(#"animation start");
[cell.layer setBackgroundColor:[UIColor colorWithRed: 180.0/255.0 green: 238.0/255.0 blue:180.0/255.0 alpha: 1.0].CGColor];
}
completion:^(BOOL finished){
NSLog(#"animation end");
[cell.layer setBackgroundColor:[UIColor whiteColor].CGColor];
}
];
}
Actually, the animation starts and ends at the same time (although animateWithDuration is set to 5). Next attempt was to skip the animation and simply set for instance a different border style:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// animate the cell user tapped on
ProductCollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ProductReuseID" forIndexPath:indexPath];
[cell.layer setBorderWidth:5.0f];
}
However, this doesn't change anything (probably because I have to redraw the cell manually?).
Do you have any ideas how to animate a UICollectionViewCell when the user tapped on it?
Kind regards,
Christian
It would appear that you are obtaining the wrong Cell. Sending the dequeueReusableCellWithReuseIdentifier:forIndexPath: message does not obtain the cell in use in the view at the indexPath in the second parameter, but dequeues a previously used but reusable cell; if no reusable cell is available, a new one is created. See Reference 1 below.
Replacing:
ProductCollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ProductReuseID" forIndexPath:indexPath];
With:
ProductCollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
In your code above, should give you the proper cell to work with.
Here is your fist example, rewritten.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath(NSIndexPath *)indexPath
{
// animate the cell user tapped on
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:5.0
delay:0
options:(UIViewAnimationOptionAllowUserInteraction)
animations:^{
NSLog(#"animation start");
[cell setBackgroundColor:[UIColor colorWithRed: 180.0/255.0 green: 238.0/255.0 blue:180.0/255.0 alpha: 1.0]];
}
completion:^(BOOL finished){
NSLog(#"animation end");
[cell setBackgroundColor:[UIColor whiteColor]];
}
];
}
References:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UICollectionView_class/Reference/Reference.html#//apple_ref/occ/cl/UICollectionView
You can customize the animation while select/tap the UICollectionViewCell with custom animation duration by following the code. So, You don't need to change the background color of it.
With following options - UIViewAnimationOption
UIViewAnimationOptionCurveEaseIn
UIViewAnimationOptionCurveEaseOut
UIViewAnimationOptionAllowUserInteraction
UICollectionViewDelegate - didSelectItemAtIndexPath method
UICollectionViewCell *uviCollectionCell = [collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:0.4 delay:0 options:(UIViewAnimationOptionCurveEaseIn) animations:^{
NSLog(#"animation start");
CALayer *layer = uviCollectionCell.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 15.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:0 options:(UIViewAnimationOptionCurveEaseOut) animations:^{
NSLog(#"animation end");
CALayer *layer = uviCollectionCell.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m24 = 0;
rotationAndPerspectiveTransform =CATransform3DRotate(rotationAndPerspectiveTransform, 0.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
} completion:nil];
}
];
Related
I have a view controller with 2 arrays, one for normal results; the other for filtered/search results based off text entry.
Only one cell can have the UITableViewCellAccessoryCheckmark at a time.
My problem can be described thusly;
IE:
View controller is fed a Venue object; and is marked with
UITableViewCellAccessoryCheckmark. This is expected, and correct.
User types in a search query, the search results array is used;
however the UITableViewCellAccessoryCheckmark is no longer on the
Venue that was previously checked in step 1.
I am not sure why its not checking the cell.
Visual examples;
Original view. Cobo Arena is the pre-selected venue
-
When typing; The checkmark is not in the right place
-
More typing: The checkmark is now gone
-
The code is below
- (void) configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
FCVenue *venue;
if (self.isSearching)
{
venue = [self.searchResults objectAtIndex:indexPath.row];
}
else
{
venue = [self.venues objectAtIndex:indexPath.row];
}
if ([indexPath isEqual:self.selectedIndexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
cell.textLabel.text = [NSString stringWithFormat:#"%#", venue.name];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", venue.location];
}
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView cellForRowAtIndexPath:self.selectedIndexPath].accessoryType = UITableViewCellAccessoryNone;
self.selectedIndexPath = indexPath;
[self.tableView reloadRowsAtIndexPaths:#[self.selectedIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
return indexPath;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
FCVenue *venue;
if (self.searching)
{
venue = [self.searchResults objectAtIndex:indexPath.row];
}
else
{
venue = [self.venues objectAtIndex:indexPath.row];
}
self.selectedVenue = venue;
// This method fires a completion block and dismisses the view controller
if (self.completionBlock)
{
self.completionBlock( self, self.selectedVenue );
}
[self.navigationController dismissViewControllerAnimated:YES completion:^{
}];
}
That's happening because you are storing the index of the full table to display the checkmark. Instead you should compare the FCVenue object to see if that is the one checked or not.
So the code should be something like this, it is not tested though:
- (void) configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
FCVenue *venue;
if (self.isSearching)
{
venue = [self.searchResults objectAtIndex:indexPath.row];
}
else
{
venue = [self.venues objectAtIndex:indexPath.row];
}
if ([venue isEqual:self.selectedVenue]) // You may want to compare just the id or any other unique property
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// if you opt for keeping the selectedIndexPath property you need to refresh it here.
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
cell.textLabel.text = [NSString stringWithFormat:#"%#", venue.name];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", venue.location];
}
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//[self.tableView cellForRowAtIndexPath:self.selectedIndexPath].accessoryType = UITableViewCellAccessoryNone;
// Here you may want to do a loop over all the possible index path to clean the state or keep storing the selected indexPath just to clear the mark when the selected venue changes.
FCVenue *venue;
if (self.searching)
{
venue = [self.searchResults objectAtIndex:indexPath.row];
}
else
{
venue = [self.venues objectAtIndex:indexPath.row];
}
self.selectedVenue = venue;
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
return indexPath;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// This method fires a completion block and dismisses the view controller
if (self.completionBlock)
{
self.completionBlock( self, self.selectedVenue );
}
[self.navigationController dismissViewControllerAnimated:YES completion:^{
}];
}
In any case the general idea is that you need to tie the venue with the check and not with at indexPath as the indexPath will change with the search.
I'm working on a weird issue right now. My Apps Deployment Target is set to iOS6, so I want to support both iOS6 and iOS7.
I just have a simple UITableView, in which the user can select the preferred notification sound.
The code for - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CheckmarkCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell setTintColor:[UIColor redColor]];
if (indexPath.section == 0){
cell.textLabel.text = [_availableSounds objectAtIndex:indexPath.row];
if (indexPath.row == _checkedSoundIndexPath.row) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
else {
// Unrelated, another settings cell
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
return cell;
}
My - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath looks like the following:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section != 0) {
return;
}
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[[self.tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
if (_checkedSoundIndexPath != indexPath) {
[[self.tableView cellForRowAtIndexPath:_checkedSoundIndexPath] setAccessoryType:UITableViewCellAccessoryNone];
}
_checkedSoundIndexPath = indexPath;
}
The problem is that an iOS7 iPhone won't show the checkmark as expected. Running the same code on an iOS6 iPhone works as expected. I tried to insert [cell setTintColor:[UIColor redColor]]; but without any luck. Even if I remove all AccessoryType related code and add the checkmark in my storyboard nothing appears. See screenshots below (first is iOS6 and second is iOS5).
Does anyone have an idea ? Or is it a bug in iOS7 ?
Thanks in advance !
Edit:
Even if I make a new simple UITableViewController, with just 5 cells with the Accessory set to UITableViewAccessoryTypeCheckmark, the Checkmarks won't appear on iOS7.
I had a similar problem and I solved this issues changing the tint color of the uitableview
I changed the tintcolot of uitable by InterfaceBuilder to Default color
or
tableView.tintColor = [UIColor blackColor];
I had the exact same problem as you are for a long time.
In my case I implemented some appearance tweaks. And one of them was
[[UIView appearance] setTintColor:[UIColor whiteColor]];
Try to find in your project global things like that.
In my application it working perfect,check it
//take it in .h file mutable arSelectedRows;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
//Do anything you want for cell here
if([arSelectedRows containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[arSelectedRows addObject:indexPath];
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
[arSelectedRows removeObject:indexPath];
}
NSLog(#"id are here :%#",arSelectedIDs);
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
may be ,it will helpful.
No, There is No Problem with UITableViewCellAccessoryCheckmark in iOS 7,Make sure you have implemented correct logic for it.
I think the problem is with your checksoundIndexpath, please check whether it has a correct indexpath, Or First check with hardcoded indexpath.
you are not initializing the checksoundindxpath.
Also I noticed you are not assigning the selected row indexpath to _checkSoundIndexpath, Only you are checking if both indexpaths(current indexpaths and _checksoundindexpath) are equal, But if they are different then you should assign the selected indedxpath to _checksound indexpath.
I can solve this problem by set tint color for Cell
It didnt show because cell tint in white ,and cell selectionstyle is none
cell.tintColor = [UIColor blackColor];
if(cell.selected){
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}else{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
I would rather reload tableview (preferably only the affected rows - using reloadRowsAtIndexPaths) after settings appropriate data in didSelectRowAtIndexPath: method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Other logic..
[tableView deselectRowAtIndexPath:indexPath animated:NO]; // Would like to look for an alternative method to avoid this refresh??
NSMutableArray *reloadArray = [NSMutableArray arrayWithCapacity:2];
[reloadArray addObject:indexPath];
[reloadArray addObject:_checkedSoundIndexPath];
self.checkedSoundIndexPath = indexPath; // Should set this before reload
[tableView reloadRowsAtIndexPaths:reloadArray withRowAnimation:UITableViewRowAnimationAutomatic];
}
And, most importantly, add these lines in cellForRowAtIndexPath: method -
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// All your other code for this section followed by these lines...
if([_checkedSoundIndexPath compare:indexPath] == NSOrderedSame) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Other sections code
return cell;
}
I know the original question uses a simple UITableViewCell but this might work for someone else with a custom table view cell.
I have a custom UITableViewCell subclass. I tried everything but the checkmark won't show. Eventually I realised that I overrode layoutSubviews but forgot to call [super layoutSubviews]. Which meant the checkmark would not show correctly.
- (void)layoutSubviews
{
[super layoutSubviews];
//...custom layout here
}
I have started iOS app development recently.
I have a problem about segue from UITableViewController to UIViewController.
"prepareForSegue" is not called when a tablecell is clicked.
It seems to me that the code and interface builder settings are fine.
Segue ID is properly set. I also embedded UITableVC in navigationVC, too.
I set the breakpoint in the prepareForSegue, but it does not stop there and no log is generated.
Through researching tips in the Internet, I understand that using didSelectRowAtIndexPath is one of the solutions for my problem.
But I would like to understand the solution by using storyboard.
This might be a basic question, but if someone could give me some tips, it could be very helpful.
thank you,
#interface test2TVC ()
#property(strong,nonatomic) NSArray *items;
#end
#implementation test2TVC
- (void)viewDidLoad
{
[super viewDidLoad];
self.items = #[#"item1", #"item2", #"item3", #"item4",
#"item5", #"item6", #"item7", #"item8"];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"test log");
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [self.items objectAtIndex:indexPath.row];
return cell;
}
#end
When I use:
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
in viewDidLoad
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath] in cellForRowAtIndexPath
prepareForSegue will not be called.
When I remove registerClass line in viewDidLoad, and
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
in cellForRowAtIndexPath, prepareForSegue will be called, other setting are all same.
Make sure that you have embedded navigation controller your UITableViewController in Mainstoryboard. or try to embed navigation controller in rootViewController of your project. Then set reuse identifier in tableviewcell. Any problem the please share it.
I have a UITableViewCell with an UICollectionView inside it. My custom UITableViewCell is responsible for the datasource and methods for the UICollectionView. All works perfectly except when I add some logging to the cellForItemAtIndexPath I see that all UICollectionViewCells will be loaded at once. So there goes my lazy/delayed loading when scrolling down.
Here is my logging in the custom UITableViewCell
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Loading cell: %i", indexPath.row);
}
The tableViewCell height is automaticaly calculated based on the items the UICollectioNView needs to handle. So in the tableview method of my ViewController:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//return dynamically the height based on the items to show in the collectionview.
}
So I guess this is my problem and reason why it doesn't do lazy loading. Is there an easy fix for this ? Or is this the way:
Source: http://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell
By this the lazy loading will only be handled by the UITableView and not the UICollectionView.
Here is the full code of my custom UITableViewCell, but as you will see this is really nothing special.
#implementation PeopleJoinedThisPlaceCell
#synthesize people = _people;
- (void)awakeFromNib
{
collectionView.delegate = self;
collectionView.dataSource = self;
collectionView.backgroundColor = [UIColor clearColor];
}
- (void)setPeople:(NSArray *)people
{
_people = people;
[collectionView reloadData];
}
#pragma mark - CollectionViewController delegate methods
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
if(_people == NULL) return 0;
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if(_people == NULL) return 0;
return _people.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView_ cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Loading cell: %i", indexPath.row);
ImageCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"People" forIndexPath:indexPath];
PFObject *userPlace = [_people objectAtIndex:indexPath.row];
PFUser *user = [userPlace objectForKey:UserClassName];
[cell.BackgroundImageView setImage:[UIImage imageNamed:#"photo-big-bg"]];
[cell.ImageLoader startAnimating];
[[UserPhotos sharedInstance] getCachedSmallPhotoForUser:user withBlock:^(UIImage *image, NSError *error) {
[cell.ImageView setImage:image];
[cell.ImageLoader stopAnimating];
}];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView_ didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
PFObject *userPlace = [_people objectAtIndex:indexPath.row];
[_delegate gotoUserProfile:userPlace];
}
#end
Code works fine until I changed UIViewController with tableView to UICollectionViewController.
Now all cells shows same image, sometimes it flipping to nil.
However textLabels are OK.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TourGridCell";
TourGridCell *cell = (TourGridCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
Guide *guideRecord = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.titleLabel.text = [guideRecord.name uppercaseString];
cell.titleLabel.backgroundColor = [UIColor clearColor];
if ([guideRecord.sights count] > 0) {
if ([[guideRecord.sights objectAtIndex:0]valueForKey:#"thumbnail"]) {
cell.imageView.image = [UIImage drawImage:[[guideRecord.sights objectAtIndex:0]valueForKey:#"thumbnail"] inImage:[UIImage imageNamed:#"MultiplePhotos"] inRect:CGRectMake(11, 11, 63, 63)];
}else {
cell.imageView.image = [UIImage imageNamed:#"placeholder2"];
}
NSMutableString *sightsSummary = [NSMutableString stringWithCapacity:[guideRecord.sights count]];
for (Sight *sight in guideRecord.sights) {
if ([sight.name length]) {
if ([sightsSummary length]) {
[sightsSummary appendString:#", "];
}
[sightsSummary appendString:sight.name];
}
}
if ([sightsSummary length]) {
[sightsSummary appendString:#"."];
}
cell.sightsTextLabel.text = sightsSummary;
cell.detailTextLabel.text = [NSString stringWithFormat:NSLocalizedString(#"%i", nil) , [guideRecord.sights count]];
cell.detailTextLabel.hidden = NO;
// cell.textLabel.alpha = 0.7;
NSPredicate *enabledSightPredicate = [NSPredicate predicateWithFormat:#"notify == YES"];
NSArray *sightsEnabled = [[[guideRecord.sights array] filteredArrayUsingPredicate:enabledSightPredicate]mutableCopy];
NSPredicate *visitedSightPredicate = [NSPredicate predicateWithFormat:#"visited == YES"];
NSArray *sightsVisited = [[[guideRecord.sights array] filteredArrayUsingPredicate:visitedSightPredicate]mutableCopy];
if ([sightsEnabled count] > 0)
{
NSLog(#"green_badge");
cell.notifyIV.image = [UIImage imageNamed:#"green_badge"];
}
else if (sightsVisited.count == 0) {
NSLog(#"new_badge");
cell.notifyIV.image = [UIImage imageNamed:#"new_badge"];
}
else
{
cell.notifyIV.image = nil;
}
}
else {
cell.notifyIV.hidden = YES;
// cell.textLabel.textColor = RGB(0, 50, 140);
cell.detailTextLabel.hidden = YES;
cell.sightsTextLabel.text = nil;
}
return cell;
}
Cell set up in storyboard,
// TourGridCell.h
#import <UIKit/UIKit.h>
#interface TourGridCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UILabel *titleLabel;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UIImageView *notifyIV;
#property (weak, nonatomic) IBOutlet UILabel *textLabel;
#property (weak, nonatomic) IBOutlet UILabel *detailTextLabel;
#property (weak, nonatomic) IBOutlet UILabel *sightsTextLabel;
#end
#import "TourGridCell.h"
#implementation TourGridCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
you may need to provide some more data for it to be possible for others to work out what the problem is. I take it you have checked that at the different times this is called the conditions are being triggered so different images are actually being instantiated and added to your UICollectionViewCell? Also I take it you are aware a UICollectionViewCell doesn't have an image property so you will need to add a property in it's subclass (if you want easy access to the view without the overhead of retrieving it using it's tag ID) and ensure the view is added as a subview ?
I think, given the symptoms you have described, such a problem can occur if you are not adding your sub-views to the UICollectionViewCell's contentView. Apple's collection views have all manner of optimisations to ensure high performance and only the subviews of the UICollectionViewCell's content view (which is itself a sub-view of UICollectionViewCell) will be consistently drawn as you expect.
Though based on what you have provided, I can't be definitive as to if this is the cause of the problem.
#implementation UICollectionViewCellSubView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_imageView = [[UIImageView alloc] initWithFrame:frame];
[self.contentView addSubview:_imageView];
}
return self;
}
- (void)prepareForReuse
{
[super prepareForReuse];
// ensure you do appropriate things
// here for when the cells are recycled
// ...
}
#end
Solution is to nullify image each time in cellForItemAtIndexPath:
cell.imageView.image = nil;
if you are doing custom drawing in your cell, you will need to inform the cell to 'redraw' itself when a cell has been 'reused'. This is perhaps easiest done by implementing the prepareForReuse method in your UICollectionViewCell subclass.
- (void)prepareForReuse {
[super prepareForReuse];
[self setNeedsDisplay];
}
Technically, we probably don't need to include [super prepareForReuse] as the documentation suggests 'The default implementation of this method does nothing'. However, it is good practice, and who knows if Apple will change the default implementation of prepareForReuse in the future.