简体   繁体   中英

iOS: Passing object to custom UITableViewCell to UIViewController via a button action on cell

I have a custom UITableViewCell , which have a button on it, IB linked to a function called:

- (IBAction)clickUse:(id)sender;

In this function, I planned to pass an object from UITableView 's data source (an object in a NSMutableArray ) to next UIViewController , when the user clicks the button on the UITableViewCell .

I set a property in the custom UITableViewCell , like this:

@property (nonatomic, retain) SomeObject *some_object;

In UITableView 's cellForRowAtIndexPath function, I pass the object to the cell:

MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
cell.some_object = [self.cellData objectAtIndex:indexPath.row];

At this moment I track the object, it's still here. But in the MyCustomCell cell, the object is gone and assigned to nil . Therefore, the object cannot be passed to next UIViewController .

What did I miss?

Perhaps it's better to use a different approach. You can give each cell button a tag. The tag value could be the row index path.

Your -tableView:cellForRowAtIndexPath: method could include the following:

MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
cell.button.tag = indexPath.row

And your -clickUse: method could look like this:

- (IBAction)clickUse:(id)sender
{
    UIButton *button = (UIButton *)sender;
    SomeObject *object = [self.cellData objectAtIndex:button.tag];

    // do stuff with your object on click
}

I recommend creating a delegate protocol to handle this. Define a delegate on the cell. In your cellForRowAtIndexPath: method, set the cell.delegate to the viewController that implements that method. Make sure to nil your delegate in your cell's dealloc and prepareForReuse methods. In my opinion, this is the solution that sets up the cleanest relationships between the objects involved. See example below.

Assigning a button target to an object that is some object other than the superview of the button always seems counterintuitive to me. Or, whenever I work on a codebase where there's a setup like that I find that it eventually gets in the way / confuses things.

Inside CommentCell.h:

@class Comment;
@class SMKCommentCell;

@protocol SMKCommentCellDelegate <NSObject>

@required
- (void)commentCellDidTapShowReplies:(SMKCommentCell *)cell;
- (void)commentCellDidTapUsername:(SMKCommentCell *)cell;

@end

@interface SMKCommentCell : UITableViewCell

@property (nonatomic, strong) Comment *comment;
@property (nonatomic, weak) id<SMKCommentCellDelegate> delegate;

@end

Inside CommentCell.m:

#pragma mark - Actions

- (IBAction)didTapShowReplies:(id)sender
{
    if ([self.delegate respondsToSelector:@selector(commentCellDidTapShowReplies:)])
    {
        [self.delegate commentCellDidTapShowReplies:self];
    }
}

- (IBAction)didTapUsername:(id)sender
{
    if ([self.delegate respondsToSelector:@selector(commentCellDidTapUsername:)])
    {
        [self.delegate commentCellDidTapUsername:self];
    }
}

Inside your viewController.m:

#pragma mark - SMKCommentCell Delegate

- (void)commentCellDidTapShowReplies:(SMKCommentCell *)cell
{
    // Do something
}

- (void)commentCellDidTapUsername:(SMKCommentCell *)cell
{
    // Do something
}

Inside cellForRowAtIndexPath:

commentCell.comment = comment;
commentCell.delegate = self;

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