简体   繁体   English

iOS:通过单元格上的按钮操作将对象传递给自定义UITableViewCell到UIViewController

[英]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: 我有一个自定义UITableViewCell ,上面有一个按钮,即IB链接到一个名为:

- (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 . 在此函数中,我计划在用户单击UITableViewCell上的按钮时,将一个对象从UITableView的数据源( NSMutableArray一个对象)传递到下一个UIViewController

I set a property in the custom UITableViewCell , like this: 我在自定义UITableViewCell设置了一个属性,如下所示:

@property (nonatomic, retain) SomeObject *some_object;

In UITableView 's cellForRowAtIndexPath function, I pass the object to the cell: UITableViewcellForRowAtIndexPath函数中,我将对象传递给单元格:

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 . 但是在MyCustomCell单元格中,对象消失了并分配给nil Therefore, the object cannot be passed to next UIViewController . 因此,该对象不能传递给下一个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: 您的-tableView:cellForRowAtIndexPath:方法可以包括以下内容:

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

And your -clickUse: method could look like this: 您的-clickUse:方法可能如下所示:

- (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. 在您的cellForRowAtIndexPath:方法中,将cell.delegate设置为实现该方法的viewController Make sure to nil your delegate in your cell's dealloc and prepareForReuse methods. 确保在单元的deallocprepareForReuse方法prepareForReuse委托prepareForReuse 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: 内部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: 内部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: 在您的viewController.m中:

#pragma mark - SMKCommentCell Delegate

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

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

Inside cellForRowAtIndexPath: 在cellForRowAtIndexPath内部:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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