How to get UITableViewCell from the handle function of UITapGestureRecognizer? - uitableview

I add UIImageView in the UITavleViewCell, and add UITapGestureRecognizer for UIImageView, how can i get the UITableViewCell in UITap event handle function (void)likeImageTap:(UITapGestureRecognizer*)tap?
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* CellIdentifier = #"TextCellIdentifier";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (nil == cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
};
UIImageView* likeImage = (UIImageView*)[cell.contentView viewWithTag:kLikeImage];
[likeImage setUserInteractionEnabled:YES];
UITapGestureRecognizer *likeImageTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(likeImageTap:)];
[likeImageTap setNumberOfTapsRequired:1];
[likeImage addGestureRecognizer:likeImageTap];
return cell;
}
- (void)likeImageTap:(UITapGestureRecognizer*)tap {
// How cam i get UITableViewCell?
UIImageView* likeImageView = (UIImageView*)[cell viewWithTag:kLikeImage];
[likeImageView setImage:[UIImage imageNamed:#"ic_liked"]];
}

CGPoint loc = [tap locationInView:self.tableView];
for (UITableViewCell* cell in self.tableView.visibleCells){
if (CGRectContainsPoint(cell.frame, loc)){
// cell is the cell you're after
}
}

Related

UITableViewCell How can I detect that the user has swiped left or Right?

I am using SWTableViewCell and I want to know the action that is triggered when the user swipe Left or Right.
you have to add Gesture Recognizer in you cellForRowAtIndexPath
UISwipeGestureRecognizer* swRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(cellSwipedRight:)];
[swRight setDirection:UISwipeGestureRecognizerDirectionRight];
[cell addGestureRecognizer:swRight];
UISwipeGestureRecognizer* swLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(cellSwipedLeft:)];
[swLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[cell addGestureRecognizer:swLeft];
and then its selector method
-(void)cellSwipedRight:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
// your code
}
}
-(void)cellSwipedLeft:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
// your code
}
}
Try this code it will works for you:
- (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];
}
UISwipeGestureRecognizer* swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(cellSwiped:)];
[swipe setDirection:UISwipeGestureRecognizerDirectionRight];
[cell addGestureRecognizer:swipe];
cell.textLabel.text = [NSString stringWithFormat:#"Cell %d", indexPath.row];
return cell;
}
- (void)cellSwiped:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
{
UITableViewCell *cell = (UITableViewCell *)gestureRecognizer.view;
NSIndexPath* indexPath = [self.tableView indexPathForCell:cell];
//..
}
}

How to take check box in table view only selected item on didSelectRowAtIndexPath

How to take selected item in table view didSelectRowAtIndexPath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
if ([selectedRowsArray containsObject:[contentArray objectAtIndex:indexPath.row]]) {
cell.imageView.image = [UIImage imageNamed:#"checked.png"];
}
else {
cell.imageView.image = [UIImage imageNamed:#"unchecked.png"];
}
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleChecking:)];
[cell.imageView addGestureRecognizer:tap];
cell.imageView.userInteractionEnabled = YES; //added based on #John 's comment
//[tap release];
cell.textLabel.text = [contentArray objectAtIndex:indexPath.row];
return cell;
}
- (void) handleChecking:(UITapGestureRecognizer *)tapRecognizer {
CGPoint tapLocation = [tapRecognizer locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
if ([selectedRowsArray containsObject:[contentArray objectAtIndex:tappedIndexPath.row]]) {
[selectedRowsArray removeObject:[contentArray objectAtIndex:tappedIndexPath.row]];
}
else {
[selectedRowsArray addObject:[contentArray objectAtIndex:tappedIndexPath.row]];
}
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:tappedIndexPath] withRowAnimation: UITableViewRowAnimationFade];
}
This wll return all indexpaths of selected rows
tableView.indexPathsForSelectedRows

Change Table View Cell's UIImage on Tap

Probably a simple fix.
I've got an image inside each cell of my table view controller and a tap gesture recognizer on it. That's working fine and logging appropriately.
What I need is for the image to change from its default state to then toggle between a "selected" state (green) and a "deselected" state (red). In other words, it's a checklist that's gray at first, then you tap the image, the image turns to a green checkmark, tap again, it turns to a red x.
Here's the catch: Had this working when it was only a matter of a conditional statement in the didSelectRowAtIndexPath method, but since I added the gesture recognizer and created the imageTapped method, I can't seem to translate it over. Therefore, otherwise helpful threads like this don't work for me.
Thanks as always. You guys are the best.
Here's the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"PlacesCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"PlacesCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
//Create ImageView
cell.imageView.image = [UIImage imageNamed:#"checkmark.png"];
//Add Gesture Recognizer
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped)];
tapped.numberOfTapsRequired = 1;
[cell.imageView addGestureRecognizer:tapped];
cell.imageView.userInteractionEnabled = YES;
[cell addSubview:cell.imageView];
return cell;
}
//Method controlling what happens when cell's UIImage is tapped
-(void)imageTapped
{
UITableViewCell *cell;
UIImage *imageDefault = [UIImage imageNamed:#"checkmark.png"];
UIImage *imageRed = [UIImage imageNamed:#"checkmark(red).png"];
UIImage *imageGreen = [UIImage imageNamed:#"checkmark(green).png"];
if (cell.imageView.image == imageDefault) {
cell.imageView.image = imageGreen;
cell.selected = true;
NSLog(#"Selected");
} else {
cell.imageView.image = imageRed;
cell.selected = false;
NSLog(#"Deselected");
}
}
i have modified your code , check it
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"PlacesCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"PlacesCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
//Create ImageView
cell.imageView.image = [UIImage imageNamed:#"checkmark.png"];
//Add Gesture Recognizer
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
tapped.numberOfTapsRequired = 1;
[cell.imageView addGestureRecognizer:tapped];
cell.imageView.userInteractionEnabled = YES;
//[cell addSubview:cell.imageView];
return cell;
}
//Method controlling what happens when cell's UIImage is tapped
-(void)imageTapped:(UIGestureRecognizer*)gesture
{
UIImageView *selectedImageView=(UIImageView*)[gesture view];
UIImage *imageDefault = [UIImage imageNamed:#"checkmark.png"];
UIImage *imageRed = [UIImage imageNamed:#"checkmark(red).png"];
UIImage *imageGreen = [UIImage imageNamed:#"checkmark(green).png"];
if (selectedImageView.image == imageDefault) {
selectedImageView.image = imageGreen;
//cell.selected = true;
NSLog(#"Selected");
} else {
selectedImageView.image = imageRed;
//cell.selected = false;
NSLog(#"Deselected");
}
}

Memory Leak UITableView

SOLUTION
Just read the answer of #Kjuly
Thanks alot
QUESTION
I used tableView with sections, each section has 4 rows, the first row it must show image from website which I used HJCache class to cache the image and avoid leaking/memory issues.
now, this code it works well and while I am scrolling fast it doesn't leak or make memory issue
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//UITableViewCell *cell=nil;
if (indexPath.row == 0) {
static NSString *CellIdentifier = #"Cell";
HJManagedImageV* mi;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
mi = [[HJManagedImageV alloc] initWithFrame:CGRectMake(0,0,cell.frame.size.width, 310)];
mi.tag = 999;
[cell addSubview:mi];
} else {
mi = (HJManagedImageV*)[cell viewWithTag:999];
[mi clear];
}
if (indexPath.row == 0) {
mi.image = [UIImage imageNamed:#"placeholder"];
mi.url = [NSURL URLWithString:[pictures objectAtIndex:indexPath.section]];
[objMan manage:mi];
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(likeTappedDouble:)];
tapped.numberOfTapsRequired = 2;
[mi setUserInteractionEnabled:YES];
[mi addGestureRecognizer:tapped];
}
return cell;
}
}
But when I try to configure other rows it leaked and while scrolling the application make memory issue and be very slowly.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//UITableViewCell *cell=nil;
if (indexPath.row == 0) {
static NSString *CellIdentifier = #"Cell";
HJManagedImageV* mi;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
mi = [[HJManagedImageV alloc] initWithFrame:CGRectMake(0,0,cell.frame.size.width, 310)];
mi.tag = 999;
[cell addSubview:mi];
} else {
mi = (HJManagedImageV*)[cell viewWithTag:999];
[mi clear];
}
if (indexPath.row == 0) {
mi.image = [UIImage imageNamed:#"placeholder"];
mi.url = [NSURL URLWithString:[pictures objectAtIndex:indexPath.section]];
[objMan manage:mi];
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(likeTappedDouble:)];
tapped.numberOfTapsRequired = 2;
[mi setUserInteractionEnabled:YES];
[mi addGestureRecognizer:tapped];
}
return cell;
}
static NSString *CellIdentifier = #"CellS";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if (indexPath.row == 1) {
// configure row 1
}
if (indexPath.row == 2) {
// configure row 2
}
// etc for the others ..
return cell;
}
Where is the problem, Thanks..
UPDATE
This code doesn't work well, it add the subview in other row while scrolling
static NSString *CellIdentifier = #"CellS";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if (indexPath.row == 1) {
UIImage* likesimage = [UIImage imageNamed:#"likespic"];
CGRect frameimg = CGRectMake(7, 5, likesimage.size.width, likesimage.size.height);
likesbutton = [[UIButton alloc] initWithFrame:frameimg];
[likesbutton setBackgroundImage:likesimage forState:UIControlStateNormal];
likesbutton.backgroundColor = [UIColor clearColor];
[cell addSubview:likesbutton];
label3 = [[UILabel alloc] initWithFrame:CGRectMake(20, 2, 100, 20)];
label3.textColor = [UIColor colorWithRed:61.0/255.0 green:113.0/255.0 blue:154.0/255.0 alpha:1.0];
label3.backgroundColor = [UIColor clearColor];
label3.font = [UIFont fontWithName:#"Helvetica-Bold" size:12];
label3.adjustsFontSizeToFitWidth = YES;
[cell addSubview:label3];
}
}
For your other cells, you need to reuse the cell either:
static NSString *CellIdentifier = #"CellS";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
EDIT for Updated Question:
You need to know how "cell reusing" works. As for your updated code, it said only row 1 needs the subviews like image, right? So you need add it outside of the if (cell == nil){} snippet, like the code below:
static NSString *CellIdentifier = #"CellS";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
if (indexPath.row == 1) {
UIImage* likesimage = [UIImage imageNamed:#"likespic"];
CGRect frameimg = CGRectMake(7, 5, likesimage.size.width, likesimage.size.height);
likesbutton = [[UIButton alloc] initWithFrame:frameimg];
[likesbutton setBackgroundImage:likesimage forState:UIControlStateNormal];
likesbutton.backgroundColor = [UIColor clearColor];
[cell addSubview:likesbutton];
label3 = [[UILabel alloc] initWithFrame:CGRectMake(20, 2, 100, 20)];
label3.textColor = [UIColor colorWithRed:61.0/255.0 green:113.0/255.0 blue:154.0/255.0 alpha:1.0];
label3.backgroundColor = [UIColor clearColor];
label3.font = [UIFont fontWithName:#"Helvetica-Bold" size:12];
label3.adjustsFontSizeToFitWidth = YES;
[cell addSubview:label3];
}
Note: It's better to create a new cell instance like what you did for row 0, cause it's only need to be created once.
try this ...
man you are doing 2 mistakes here
not checking for dequeued cells.
after allocating the cell , you are not releasing it's memory.
i suggest this code for you .
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cellID";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}
}
don't forget to autorelease cells .
remove all add subviews, then add new subviews
NSArray *subviews = [[NSArray alloc] initWithArray:cell.contentView.subviews];
for (UIView *subview in subviews) {
[subview removeFromSuperview];
}

UITapGestureRecognizer on UIImageView within UITablevlewCell not getting called

I currently have a custom UITableViewCell which contains a UIImageView and trying to add a UITapGestureRecognizer on the UIImageView with no luck. here is snippet of the code.
//within cellForRowAtIndexPath (where customer table cell with imageview is created and reused)
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleImageTap:)];
tap.cancelsTouchesInView = YES;
tap.numberOfTapsRequired = 1;
tap.delegate = self;
[imageView addGestureRecognizer:tap];
[tap release];
// handle method
- (void) handleImageTap:(UIGestureRecognizer *)gestureRecognizer {
RKLogDebug(#"imaged tab");
}
I've also set userInteractionEnabled on the cell and the superview of the UIImageView but still no luck, any hints?
EDIT:
I've also remove cell's selection by cell.selectionStyle = UITableViewCellSelectionStyleNone; Could this be a problem
UIImageView's user interaction is disabled by default. You have to enable it explicitly to make it respond to touches.
imageView.userInteractionEnabled = YES;
Swift 3
This worked for me:
self.isUserInteractionEnabled = true
In my case it looks like :
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = CELL_ROUTE_IDENTIFIER;
RouteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[RouteTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier];
}
if ([self.routes count] > 0) {
Route *route = [self.routes objectAtIndex:indexPath.row];
UITapGestureRecognizer *singleTapOwner = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(imageOwnerTapped:)];
singleTapOwner.numberOfTapsRequired = 1;
singleTapOwner.cancelsTouchesInView = YES;
[cell.ownerImageView setUserInteractionEnabled:YES];
[cell.ownerImageView addGestureRecognizer:singleTapOwner];
} else {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
return cell;
}
And selector :
- (void)imageOwnerTapped:(UISwipeGestureRecognizer *)gesture {
CGPoint location = [gesture locationInView:self.tableView];
NSIndexPath *tapedIndexPath = [self.tableView indexPathForRowAtPoint:location];
UITableViewCell *tapedCell = [self.tableView cellForRowAtIndexPath:tapedIndexPath];
NSIndexPath *indexPath = [self.tableView indexPathForCell:tapedCell];
NSUInteger index = [indexPath row];
Route *route = [self.routes objectAtIndex:index];
}

Resources