1

I understand how to get button clicks if I have a button within a row of UITableView but what I cannot figure out is the correct way to add a button to a UITableViewCell subclass and get the clicks for it within my UITableView class. I think I'm making the mistake of putting everything into the layoutSubviews method. Can somebody please point me in the right direction?

-(void) layoutSubviews 
{
//  UIButton *myButton1; <- This is declared as a property in my subclass header file

  [super layoutSubviews];

  //self.textLabel.frame = CGRectMake(0, 0, 40, 20);

  //        cell.textLabel.text = timeElapsed;
  self.textLabel.frame = CGRectMake( 5, 5, 80, self.frame.size.height - 10 );
  self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;   

  // Don't need UIButton alloc because method below does it for us..
  myButton1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];

  //CGRect cellFrame = [self.tableView rectForRowAtIndexPath:indexPath];
  CGRect cellFrame = self.frame;

  myButton1.tag = idButton;

  int nButtonWidth  = 80;
  int nButtonHeight = 30;
  int nActualCellWidth = cellFrame.size.width - 40;
  int nButtonDeltaX = ( nActualCellWidth      - nButtonWidth  ) / 2;
  int nButtonDeltaY = ( cellFrame.size.height - nButtonHeight ) / 2;
  myButton1.frame = CGRectMake( nButtonDeltaX, nButtonDeltaY, nButtonWidth, nButtonHeight );      

  [myButton1 setTitle:@"OK" forState:UIControlStateNormal];

  // PDS: Add delaget for stopwatch clicking..
//  [myButton1 addTarget:self action:@selector(buttonClickedStopWatch:) forControlEvents:UIControlEventTouchUpInside];  

  [self.contentView addSubview:myButton1];      
  [self.contentView bringSubviewToFront:myButton1];
}
SparkyNZ
  • 6,266
  • 7
  • 39
  • 80

1 Answers1

5

First of all, layoutSubviews may be called multiple times so that's really not a good place to create a button and add it to the view hierarchy. This will cause a new button to be created each time. You should rather create the button in your designated initializer and only use layoutSubviews for setting frames and such.

Second, an instance of UITableView is not usually a good place to handle button clicks. That's commonly a task for a subclass of UIViewController.

Whichever class you select for handling the tap action, start by adding a property in the cell for your custom button. Then let the UITableView or UIViewController add the action target for that control event by accessing the property and setting target to self.

Anton
  • 5,932
  • 5
  • 36
  • 51
  • That sounds good, thanks. It will be the UITableViewController class I'm referring to rather than the UITableView sorry.. I think.. Don't have my Mac with me at the moment. So in regard to adding the buttons and initilising, I just need to add a method of my own to do the initialisation and call that on my custom cell object. Cool. So will layoutSubviews be called everytime the text property of a label is changed? (I would be changing the content of a label within cellForRowAtIndexPath.) – SparkyNZ Jul 03 '12 at 20:42
  • 1
    The designated initializer of UITableViewCell is initWithStyle:reuseIdentifier: so you could implement this method and add the subviews there. The layoutSubviews method of the cell will not triggered by setting the text property of a label in the cell, but it will for instance be called each time the frame of the cell is changed. See this question for more information: http://stackoverflow.com/questions/728372/when-is-layoutsubviews-called – Anton Jul 03 '12 at 20:52
  • I can't get the click to call my UITableViewController method: PeriodCell *cellPeriod = (PeriodCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cellPeriod == nil) { cellPeriod = [[[PeriodCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; // PDS: Initialise my button on the cell etc [cellPeriod initPeriodCell]; [cellPeriod.myButton1 addTarget:self action:@selector(buttonClickedStopWatch:) forControlEvents:UIControlEventTouchUpInside]; } – SparkyNZ Jul 04 '12 at 09:26
  • Actually.. it does work. My 1 second timer seems to be stopping things from working.. so I must have understood you OK. I'm going to accept your answer. – SparkyNZ Jul 04 '12 at 09:30
  • 1
    Great! I would advice you to move the code in initPeriodCell to initWithStyle:reuseIdentifier: to avoid having two init methods. – Anton Jul 04 '12 at 09:35