简体   繁体   中英

Need to take Action on UIButton press that is in nested TableViews with custom UITableViewCell

I have a UITableViewController (called Details). In that tableView on row 1 I have another UITableView which I rotate horizontally. Each cell in that tableview is a custom UITableViewCell (called DetailsHorizontalPhotoCell) which displays a button with an image. I am having a hard time taking action when the photos (the buttons) are pressed.

Calling an IBAction is not a problem for me if I have that IBAction code in the DetailsHorizontalPhotoCell.h/.m files however I need to present a modal VC upon the button presses. That code does not belong and/or work in a tableViewCell - it needs to be in the controller (Details). That being said I can't figure out how to code it. This is what I have so far.

Details.m:

if( (indexPath.row == 1) && ([detailsObject_.photo count] > 0) )
{
    NSLog(@"** In Photo Section **");

    static NSString *CellIdentifier = @"cellPhoto";
    DetailsHorizontalPhotoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil)
    {
        cell = [[DetailsHorizontalPhotoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    CGAffineTransform rotateTable = CGAffineTransformMakeRotation(-M_PI_2);
    cell.horizontalTableView.transform = rotateTable;

    NSArray *photoArray = [[NSArray alloc] initWithArray:detailsObject_.photo];

    cell.horizontalTableView.frame = CGRectMake(0, 0, cell.horizontalTableView.frame.size.width, cell.horizontalTableView.frame.size.height); 
    cell.contentArray = [NSArray arrayWithArray:photoArray];
    cell.horizontalTableView.allowsSelection = YES;

    return cell;
}

DetailsHorizontalPhotoCell.m:

@synthesize horizontalTableView = horizontalTableView_;
@synthesize contentArray = contentArray_;
@synthesize imageButton = imageButton_;

// *** a bunch of code which is not relevant to this question snipped out here... 


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [self.horizontalTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
    }

    for(UIButton *button in cell.subviews)
    {
        [button removeFromSuperview];
    }

    // create image and button
    UIImage *image = [UIImage imageNamed:[contentArray_ objectAtIndex:indexPath.row]];
    self.imageButton = [[UIButton alloc] initWithFrame:CGRectMake(5, 5, 240, 240)];

    // setup the button
    [imageButton_ setImage:image forState:UIControlStateNormal];
    imageButton_.layer.masksToBounds = YES;
    imageButton_.layer.cornerRadius = 5.0;
    imageButton_.layer.borderWidth = 1.0;
    imageButton_.layer.borderColor = [[UIColor grayColor] CGColor];

    // rotate the button
    CGAffineTransform rotateButton = CGAffineTransformMakeRotation(M_PI_2);
    imageButton_.transform = rotateButton;

    // this detects the click of each photo and triggers the IBAction
    [imageButton_ addTarget:self action:@selector(photoButton:) forControlEvents:UIControlEventTouchUpInside];

    /// do more stuff yada yada yada... <snipped code> and return cell;
}


// the Action (which I know should NOT be in this UITableViewCell class)
- (IBAction)photoButton:(id)sender 
{
    CGPoint hitPoint = [sender convertPoint:CGPointZero toView:self.horizontalTableView];
    NSIndexPath *hitIndex = [self.horizontalTableView indexPathForRowAtPoint:hitPoint];

    NSLog(@"Image clicked, index: %d", hitIndex.row);

    // presentModalViewController here - but you can't do that from here! Must be in the Details controller
}

So, knowing that I can't perform a presentModalViewController from the Cell I try to move that code into the Details class (below)

Add the IBAction to Details.h and .m

- (IBAction)photoButton:(id)sender 
{
    DetailsHorizontalPhotoCell *cell = [[DetailsHorizontalPhotoCell alloc] init];

    CGPoint hitPoint = [sender convertPoint:CGPointZero toView:cell.horizontalTableView];
    NSIndexPath *hitIndex = [cell.horizontalTableView indexPathForRowAtPoint:hitPoint];

    NSLog(@"Image clicked, index: %d", hitIndex.row);
}

And add the click event to the photo button in the Details cellForRowAtIndexPath method.

// Blaaahh! Tried a million combinations of something like below but cannot get it to work... 
//[cell.imageButton addTarget:cell.horizontalTableView action:@selector(photoButton:) forControlEvents:UIControlEventTouchUpInside];

PS - I'm using IOS5, Xcode 4.2 w/ ARC

First of all there is no need to add the button each time a cell is displayed. You only have to add the subviews of the cell when you create a new cell. You'll get better scrolling performance this way.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [self.horizontalTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        [cell setSelectionStyle:UITableViewCellSelectionStyleNone];

        // Add image button to cell
        UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(5, 5, 240, 240)];
        // set tag so you can get the button later
        button.tag = 1021;
        [button addTarget:self action:@selector(photoButton:) forControlEvents:UIControlEventTouchUpInside]
        // more button config
        [cell.contentView addSubView:button];
    }
    // get image button
    UIButton *button = [cell.contentView viewWithTag:1021];
    // configure image button
    UIImage *image = [UIImage imageNamed:[contentArray_ objectAtIndex:indexPath.row]];
    [button setImage:image forState:UIControlStateNormal];
    return cell;
}

Next you can use use superview on the button (= sender) to go back to the UITableViewCell. With the cell you can get the indexPath of that cell.

- (IBAction)photoButton:(id)sender 
{
    UIView *contentView = [sender superview];
    UITableViewCell *cell = [contentView superview];
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
}

Are you having trouble detecting the button press or are you having trouble getting presentModalViewController to work from with in the tableview? If you having trouble detecting the button press then you might simply need:

[button setExclusiveTouch:YES];

If your having trouble because you cannot use presentModalViewController from within the tableView then yo might be able to use:

[[NSNotificationCenter defaultCenter] addObserver: selector: name: object:];

To notify your "Details class" to use presentModalViewController

您可以使用[[button superview] superview]添加特定的TAG或访问uitableview

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM