22

searched already some possible fixes but all did not solve mine.

i keep clicking the cell in the uitableview rather than the buttons inside it.

here is my code:

- (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.backgroundColor = [UIColor blackColor];

    UIView *v  = nil;
    NSArray *array = [cell subviews];

    for (v in array) {
        NSLog(@"%@",[v class]);
        if( [v isKindOfClass:[UIView class]] ){
           [v removeFromSuperview];
        }
    }

    //tb
    if (tableView == self.tb) {

        v = [[UIView alloc] initWithFrame: CGRectMake(0, 0, self.tb.bounds.size.width, 120.0)];

        if([feeds count]>0){
            UIImageView *box=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"statusBox.png"]];

            box.userInteractionEnabled = YES;
            [v addSubview:box];

            AsyncImageView *imageView1 = [[AsyncImageView alloc] initWithFrame:CGRectMake(10, 20.0f, 34.0f, 34.0f)];
            imageView1.contentMode = UIViewContentModeScaleAspectFill;
            imageView1.clipsToBounds = YES;

            //cancel loading previous image for cell
            [[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget:imageView1];
            if (users1 != nil && users1.imagelink != nil && (id) users1.imagelink !=   [NSNull null]){
               imageView1.imageURL = [NSURL URLWithString:users1.imagelink];
            }
            else{
                imageView1.image=[UIImage imageNamed:@"default_ProfilePic.png"];
            }

            UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(myFunction:)];
            tapped.numberOfTapsRequired = 1;
            [imageView1 addGestureRecognizer:tapped];
            [tapped release];

            imageView1.userInteractionEnabled = NO;
            [v addSubview:imageView1];


            UIFont *font     = [UIFont fontWithName:@"TrebuchetMS-Bold" size:11];
            UILabel *descLabel1 = [[UILabel alloc] initWithFrame: CGRectMake(52, 23, 160, 48)];
            descLabel1.text                 = [NSString stringWithFormat:@"%@ %@",users1.userfirstn,users1.userlastn];
            descLabel1.textColor            = [UIColor blackColor];
            descLabel1.font                 = font;
            descLabel1.adjustsFontSizeToFitWidth=YES;
            descLabel1.numberOfLines = 0;
            CGSize expectedLabelSize = [descLabel1.text sizeWithFont:descLabel1.font
                                               constrainedToSize:descLabel1.frame.size
                                                   lineBreakMode:UILineBreakModeWordWrap];

            CGRect newFrame = descLabel1.frame;
            newFrame.size.height = expectedLabelSize.height;
            descLabel1.frame = newFrame;
            descLabel1.numberOfLines = 0;

            descLabel1.userInteractionEnabled = NO;
            [v addSubview:descLabel1];


            UILabel *descLabel2= [[UILabel alloc] initWithFrame: CGRectMake(52, 43, 200, 48)];
            StatusClass *stat1=[feeds objectAtIndex:indexPath.row];
            descLabel2.text                 = [stat1 statcreate];
            descLabel2.textColor            = [UIColor blackColor];
            descLabel2.font                 = font;
            descLabel2.adjustsFontSizeToFitWidth=YES;
            descLabel2.numberOfLines = 0;
            CGSize expectedLabelSize2 = [descLabel2.text sizeWithFont:descLabel2.font
                                                constrainedToSize:descLabel2.frame.size
                                                    lineBreakMode:UILineBreakModeWordWrap];

            CGRect newFrame2 = descLabel2.frame;
            newFrame2.size.height = expectedLabelSize2.height;
            descLabel2.frame = newFrame2;
            descLabel2.numberOfLines = 0;

            descLabel2.userInteractionEnabled = NO;
            [v addSubview:descLabel2];

            UILabel *descLabel3= [[UILabel alloc] initWithFrame: CGRectMake(10, 63, 280, 80)];
            StatusClass *stat=[feeds objectAtIndex:indexPath.row];
            descLabel3.text                 = [stat stattext];
            descLabel3.textColor            = [UIColor blackColor];
            descLabel3.font                 = font;
            descLabel3.adjustsFontSizeToFitWidth=YES;
            descLabel3.numberOfLines = 0;

            descLabel3.userInteractionEnabled = NO;
            [v addSubview:descLabel3];

            //comment button
            UIButton *buttonC = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            [buttonC addTarget:self action:@selector(sendComment:) forControlEvents:UIControlEventTouchUpInside];
            [buttonC setImage:[UIImage imageNamed:@"comment.png"] forState:UIControlStateNormal];
            buttonC.frame = CGRectMake(2, 160, 145, 35);

            buttonC.userInteractionEnabled = YES;
            [v addSubview:buttonC];

            //share button
            UIButton *buttonS = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            buttonS.tag = indexPath.row;
            [buttonS addTarget:self action:@selector(sendShare:) forControlEvents:UIControlEventTouchUpInside];
            [buttonS setImage:[UIImage imageNamed:@"share.png"] forState:UIControlStateNormal];
            buttonS.frame = CGRectMake(150, 160, 140, 35);

            buttonS.userInteractionEnabled = YES;
            [v addSubview:buttonS];

        }
        v.userInteractionEnabled = YES;
        [cell addSubview:v];
    }
    return cell; 
}

I also tried the UITapGestureRecognizer for the buttons and still not working.

Thanks.

HRM
  • 2,097
  • 6
  • 23
  • 37
Long Neutrals
  • 221
  • 1
  • 2
  • 3
  • 1
    set the selection style to none – Agent Chocks. Sep 18 '13 at 07:47
  • 4
    I'm just wondering that the button's y offset is given as 160 and your view v's height is 120. So how you able to see the button? – HRM Sep 18 '13 at 08:28
  • GOOD EYES.... thank you. haven't notice that one. thats why its not clickable cause its not in the view. its working fine now – Long Neutrals Sep 18 '13 at 08:41
  • Comment added as an answer.. – HRM Sep 18 '13 at 08:57
  • I run into this same situation a couple of times per project. When it doesn't work as intended, whenever you add a button as a subview to anything, that 1) parent view has to be able to accept touch actions, isUserInteractionEnabled = true. 2) the view is added into the parent view correctly, and not just visible. This can happen easily with cells, it's visible on the screen but the views are outside of the bounds of the cell...it will never be clickable. – fonz Nov 21 '17 at 16:06

14 Answers14

53

I'm just baffled by this issue....

I managed to fix this problem by doing this on one project:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("RegCell", forIndexPath: indexPath) as! CustomCell

    cell.contentView.userInteractionEnabled = false // <<-- the solution

    return cell
}

but the same did not work for a different project. I have no idea why...

Mateusz266
  • 771
  • 9
  • 13
  • 1
    thanks!! maybe we're doing slightly different things, true fixed it for me: cell.contentView.isUserInteractionEnabled = true // <<-- the solution – Simon Briggs Nov 15 '17 at 06:06
  • @SimonBriggs, you are right! "true" fixed it for me, too :) – Emil Sabitov Sep 26 '20 at 16:54
  • 1
    `false` worked for me - perhaps i'm adding the content wrong and the contentView was taking my clicks. But it's been working since iOS 8 and broke on XCode 12.1. – bendytree Oct 22 '20 at 03:46
36

There is another potential cause of problems like this one, and that is UITableViewCells now have a contentView. This can and will be placed in front of other views in your custom table view cells in order to pick up touches and detect cell selection. In doing so, it may block touches to any views behind it. I've especially noticed this annoyance when creating cells using nibs.

The accepted means for dealing with this is to ensure that all subviews are added not to the tableview cell itself, but to its contentView. This is a read-only property that adjusts its own frame under certain circumstances, for example when slid sideways to reveal the delete button, or during editing mode. You should therefore ensure that any items you do add to the contentVieware intelligently sized and have the correct resizing behaviour.

Also be aware that by adding cells to the contentView, you may yourself block touches to it and thus prevent the cell from being selected. I personally try not to allow cell selection in tableviews containing cells with custom user-enabled controls. It only leads to confusion and awkward interfaces. In fact, I'm seriously considering replacing all UITableViews in my future projects with UICollectionViews, which are far more adaptable.

-Ash

Ash
  • 9,064
  • 3
  • 48
  • 59
  • ¿can you still use XIB files and add what you design to the contentView instead of the view itself? – calql8edkos Sep 25 '14 at 14:23
  • You can create table view cells in a nib or storyboard so long as you either use UITableView's ability to create prototype cells, or build on top of a table view cell object and register the nib with the table view using registerNib:forCellWithReuseIdentifier: - I usually use prototype cells to keep everything neat. – Ash Sep 26 '14 at 07:45
14

I was doing this:

let plusButton: UIButton = {
    let v = UIButton()
    v.setImage(plusImg, for: .normal)
    v.tintColor = .dark
    v.translatesAutoresizingMaskIntoConstraints = false


    // adding targets here did not work
    v.addTarget(self, action: #selector(plusButtonHandler), for: .touchUpInside)


    return v
}()

And it appears invoking the addTarget method inside of the closure did not work.

When I factored the addTarget method out and instead put it in the initializer, everything worked!

pkamb
  • 33,281
  • 23
  • 160
  • 191
Lord Fresh
  • 636
  • 8
  • 15
  • 2
    This worked for me after going through a lot of solutions. Thanks a lot :) – Jogendra Kumar Oct 22 '19 at 20:01
  • Yes, this is a tricky issue, hard to find. After test on a small project, I found if I set this button as `lazy` it also would work, otherwise put `addTarget` inside `init()`. – Zhou Haibo Jul 29 '21 at 05:03
13

In my case I tried to added the UIButton direct to the cell by self.addSubview(myButton), so I changed to self.contentView.addSubview(myButton) and it worked

It seems the contentView was in front of the myButton so the button won't receive the tap gesture.

Tai Le
  • 8,530
  • 5
  • 41
  • 34
  • 1
    This solution worked for me after updating to xcode 12 – tospig Sep 22 '20 at 09:51
  • This solution worked for me after my phone updated to 14 from 13. I was using Xcode 12 in both cases. The question I have is will this now fail on 13? – Brian Reinhold Jan 13 '21 at 12:41
  • I tried this and it is fixed on iOS 13, now still work on iOS 14 – Tai Le Jan 14 '21 at 13:41
  • In my case, button in a custom class was not responding to clicks that was added to tableview cell. After adding the button to the "self.contentview" instead of "self", it worked. – truespan Mar 23 '21 at 07:30
5

Your UIButton='s y offset is given as 160 and UIView's height is just given as 120. Please change the UIButton's y offset and try.

KlimczakM
  • 12,576
  • 11
  • 64
  • 83
HRM
  • 2,097
  • 6
  • 23
  • 37
4

The UITableViewCell is handling all the gestures by default. Set cell.selectionStyle = UITableViewCellSelectionStyleNone; to make it disable the default behaviour.

Rickye
  • 1,023
  • 1
  • 9
  • 16
4

For Swift 3 and Storyboard

For me, I had to enable multiple touch inside the content view, and enable user interaction on everything - the table view, table view cell, content view, and UIButton. I was using storyboard.

I also set up my tableview cell as a subclass.

Since I couldn't find an answer here when I was exploring the problem, I posted another question on stack overflow about this. You can see my code and download a project with this working here: Can't click button inside UITableViewCell?

Community
  • 1
  • 1
Nick
  • 155
  • 1
  • 2
  • 14
  • adding target inside the custom cell ( cellForRowAt ) did work as suggested inside the code. – Max May 09 '17 at 18:46
  • Weird I have never encountered this before but for some reason on this tableview this was the case. Anyway thank you! – Paul Lehn Feb 13 '18 at 21:31
3

I ran into this problem, but in my case it was not related to the table view, instead it was because I was using subviews in my button for which userInteractionEnabled was true, setting that value for false (NO) for all the button's subviews fixed the issue for me.

ThomasW
  • 16,981
  • 4
  • 79
  • 106
1

I have the same issue, and somehow I figured out my mistake.
After I changed the constraints with self(UITableViewCell) to constraints with contentView of self(UITableViewCell),my cell's button is clickable again.

wj2061
  • 6,778
  • 3
  • 36
  • 62
  • Changing my constraints from self(UITableViewCell) to constraints with contentView of the cell, it causes my buttons/textView to disappear from the cell. This is bizarre. – Weston Mitchell Jul 01 '21 at 18:22
  • I just fixed it by keeping the contentView as the cell's constraint and removing two constraints I had on the height of the contentView and textview that were there trying to fix the initial bug. All subviews are properly constrained from top to bottom and that worked!! thanks @wj2061 – Weston Mitchell Jul 01 '21 at 19:38
1

Update swift 4.2

in func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

add it : cell.buttonCheckBox.isUserInteractionEnabled = false

OR, uncheck User Interaction Enabled inspector enter image description here

Now you can select the button as well as a cell. This works for me :)

Ali
  • 131
  • 1
  • 8
0

Create a custom UITableViewCell. Refer this link.

Say you have a UIButton by the name of displayButton, you can do something like this:

Inside your - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath, after you create your cell,

[cell.dislayButton addTarget: self
                             action: @selector(replyButtonPressed:withEvent:)
                   forControlEvents: UIControlEventTouchUpInside];

And the create the method like so in your ViewController:

- (void) replyButtonPressed: (id) sender withEvent: (UIEvent *) event
{
    UITouch * touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView: self.tableView];
    NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint: location];
}
Anil
  • 2,430
  • 3
  • 37
  • 55
  • i have a programmatically made UIButton inside the tableview called "buttonC" and i tried what you want me to do. the [cell.buttonC addTarget: self action etc...]; but the problem is the cell cant find the buttonC so its giving me an error. – Long Neutrals Sep 18 '13 at 08:08
  • Instead of [buttonS addTarget:self action:@selector(sendShare:) forControlEvents:UIControlEventTouchUpInside]; Add the following: [buttonS addTarget: self action: @selector(replyButtonPressed:withEvent:) forControlEvents: UIControlEventTouchUpInside]; – Anil Sep 18 '13 at 08:47
0

try this

public override void SetSelected(bool selected, bool animated)
    {
       // this.interestsButton.Selected = true;
        if (selected)
        {
            //  this.TextLabel.TextColor = UIColor.Red;

            //this.interestsButton.ShowsTouchWhenHighlighted = true;
            this.interestsButton.BackgroundColor = UIColor.Purple;
            //this.interestsButton.SetTitleColor(UIColor.Red, UIControlState.Highlighted);
        }
        else
        {

        }


       // cell.ContentView.UserInteractionEnabled = false;
        base.SetSelected(selected, animated);


    }

Tested on "Mvvmcross.iOS" only

Komicon
  • 11
  • 5
0

Just to add to the discussion:

FOR SWIFT 5+

Is important to set the variable as lazy var when invoking the addTarget method inside of the closure. See:

lazy var plusButton: UIButton = {
    let v = UIButton()
    v.setImage(plusImg, for: .normal)
    v.tintColor = .dark
    v.translatesAutoresizingMaskIntoConstraints = false
    v.addTarget(self, action: #selector(plusButtonHandler), for: .touchUpInside)
    return v 
}() 

Now, about the contentView of the tableViewCells that appears above the cell stoping the click at the cell: I used the code above and also set the contentView to .ishidden = true and it worked!

Probably there is something linked to the lifecycle of the methods.

Hope it helps too.

Gáudio
  • 1
  • 1
-1

If you have no alternative selector for the UIButton pressed inside some UITableViewCell you need turn off userInteractionEnabled for the button

cellButton.userInteractionEnabled = false

In this case any button touch will propagate to the cell touch.

malex
  • 9,874
  • 3
  • 56
  • 77