Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Jack Ryder
7,286 PointsHow to add a button to a PhotoCell
Basically i have a collectionView and a custom cell in which i want to put a button that can be tapped to like the picture but i don't want to put the button code in the photo cell in order to keep it as simple as possible. How would i put the code for the button in my main viewController in cellForItemAtIndexPath i guess?
thanks!
6 Answers
Thomas Nilsen
14,957 PointsI'll just provide an example here based on the photo browsing app here on treehouse:
In you PhotoCell.h file you create a protocol:
@class PhotoCell;
@protocol PhotoCellDelegate <NSObject>
- (void)didPressButtinInImageView:(PhotoCell *)photoCell;
@end
@interface PhotoCell : UICollectionViewCell
@property (nonatomic) UIImageView *imageView;
@property (nonatomic) NSDictionary *photo;
@property (nonatomic, weak) id <PhotoCellDelegate> delegate;
@end
in the m.file you make a button, add it as a subview, and add a target (to receive touch)
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Alloc and add the imageview, set an image to the imageview
self.imageView = [[UIImageView alloc] init];
//self.imageView.image = [UIImage imageNamed:@"Treehouse"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[button setFrame:CGRectMake(0, 0, 40, 40)];
[button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
UITapGestureRecognizer *tab = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(like)];
tab.numberOfTapsRequired = 2;
[self addGestureRecognizer:tab];
[self.contentView addSubview:self.imageView];
[self.contentView addSubview:button];
}
return self;
}
- (void)buttonPressed:(UIButton *)sender
{
[_delegate didPressButtinInImageView:self];
}
Now all you have to do is implement the new custom delegate protocol we've just made in our viewController. A few things are required:
@interface PhotosViewController () <UIViewControllerTransitioningDelegate, PhotoCellDelegate> //add the protocol here
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
PhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"photo" forIndexPath:indexPath];
cell.backgroundColor = [UIColor lightGrayColor];
cell.photo = self.photos[indexPath.row];
cell.delegate = self; // set the delegate for every cell in our collectionView
return cell;
}
and finally do something in our method:
- (void)didPressButtinInImageView:(PhotoCell *)photoCell
{
NSIndexPath *indexPath = [self.collectionView indexPathForCell:photoCell];
NSLog(@"This photo was taken by: %@", self.photos[indexPath.row][@"caption"][@"from"][@"full_name"]);
}
Hope this helps :)
You have said so yourself, you could just implement a method that handles everything inside you PhotoCell.m instead of delegation. Maybe Amit Bijlani has some input on what the best course of action would be
Thomas Nilsen
14,957 PointsI don't understand what you mean by keeping it as simple as possible. Putting the UIbutton code in the custom cell implementation is actually what you should do :). But, if you want to do that in cellForItemAtIndexPath, it would look something like this (this is based on custom cell in a tableView, but the concept is still the same)
TNSwipeableCell *cell = (TNSwipeableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[TNSwipeableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UIButton *test = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[test setFrame:CGRectMake(20, 140, 50, 50)];
[cell insertSubview:test aboveSubview:cell.topLayerView]; //topLayerView is the topmost view in my custom cell, the button is placed above it
return cell;
Jack Ryder
7,286 PointsThanks for the response, but what i meant was the button logic. I have a button in my PhotoCell that i want to, when pressed, like the photo. I've got the logic for this but unsure as to where to put it in CellForItem
Thomas Nilsen
14,957 PointsYou could use a delegation pattern. If you're unsure of what I mean by this, then say so and I'll provide an example :) Or send me your code and I can implement it for you, and I'll send it back ;)
Jack Ryder
7,286 PointsThanks Thomas! That would be great if you could give me an example/ explain that. Still learning! haha
Thomas Nilsen
14,957 PointsDo you mind sending me the code through a dropbox link or something? It's faster for me to just implement it there so you can have a look :)
Jack Ryder
7,286 Pointswhat parts do you need?
Thomas Nilsen
14,957 Pointsyou can just zip the entire project ;)
Jack Ryder
7,286 PointsI've put the parts on paste bin for now if thats okay! http://pastebin.com/jXcS8uLc
Thomas Nilsen
14,957 PointsIf you use the delegation pattern you should be able to access the cell properties. The method we made:
- (void)didPressButtinInImageView:(PhotoCell *)photoCell
{
NSIndexPath *indexPath = [self.collectionView indexPathForCell:photoCell];
NSLog(@"This photo was taken by: %@", self.photos[indexPath.row][@"caption"][@"from"][@"full_name"]);
}
this method has a referenece to whatever cell was tapped (photoCell) and you can it's properties here.
Jack Ryder
7,286 PointsJack Ryder
7,286 PointsThats brilliant thanks Thomas i shall give this a try, thanks a million!
Jack Ryder
7,286 PointsJack Ryder
7,286 PointsAlso Thomas, wondered how i would then access my button in the cell from that method to change the image when it changes to UIControlStateSelected for example.
I know that i would need this code:
[cell.likeButton setImage:[UIImage imageNamed:@"redstar"] forState:UIControlStateSelected];but because i'm not in cellForItem and in the method i can no longer access the cell and the button property i've set.
Thanks in advance!