向 UIControls 添加属性而不进行子类化

Posted

技术标签:

【中文标题】向 UIControls 添加属性而不进行子类化【英文标题】:Adding properties to UIControls without subclassing 【发布时间】:2011-12-13 16:30:08 【问题描述】:

我在 TableViewCells 中嵌入了 UIButton。为了跟踪按钮属于哪个单元格,我想向 UIButton 添加一个 NSIndexPath 属性。我不想继承 UIButton。有没有办法可以用类别来做到这一点?

编辑:如果我在表格视图中有多个部分,我相信设置标签的想法将不起作用。访问按钮的超级视图的超级视图以确定单元格的另一种方法似乎更像是一种 hack。寻找一种更清洁的方法。

【问题讨论】:

【参考方案1】:

有几种方法。如果你真的需要一个数字而不是完整的索引路径,你可以使用setTag:。它不灵活,但很容易获得。

下一个最佳解决方案是associative references。这些可以通过适当的内存管理将数据挂在任何对象上。我通常创建一个类别,添加使用objc_setAssociatedObjectobjc_getAssociatedObject 实现的属性。

【讨论】:

【参考方案2】:

您无需将标签或索引路径与按钮关联即可找出单击的按钮所在的单元格,这在重复使用单元格时会变得混乱。标签确实适用于分段表,但您必须弄乱数字,例如10001 是第 1 部分,第 1 行,因此您必须在一端转换并在另一端转换回来,这对我来说太脆弱了。

更好的方法是使用 UITableView 的indexPathForRowAtPoint: 方法。当您的按钮动作被激活时(假设目标在您的表格视图控制器中:

CGPoint point = [sender convertPoint:sender.center toView:self.tableView];
NSIndexPath *path = [self.tableView indexPathForRowAtPoint:point];

sender 这里被转换为UIButton

【讨论】:

【参考方案3】:

为了跟踪按钮属于哪个单元格

您已经知道按钮属于哪个单元格:它是按钮所在的单元格的子视图。

    从对按钮的引用开始。 (如果您按钮,则为self。如果您是按钮的操作目标,那么当点击按钮并发出操作消息时,它会将自身作为参数传递给操作消息,通常称为sender。)

    查找视图层次结构 (superview) 以找到包含该按钮的 UIViewTableCell。

    UIView* v = theButton;
    while (![v isKindOfClass: [UITableViewCell class]]) v = v.superview;
    

    现在您可以使用该信息做任何您想做的事情。例如,您似乎想要一个 NSIndexPath;然后拨打-[UITableView indexPathForCell:]

【讨论】:

以上是关于向 UIControls 添加属性而不进行子类化的主要内容,如果未能解决你的问题,请参考以下文章

为 DismissViewController 添加通知而不进行子类化

我可以向 NSManagedObject 的子类的子类添加属性吗?

UIView 的子类没有视图属性

delaysContentTouches 仅针对特定元素而不进行子类化?

python中子类在实例化时,能否增添父类没有的初始属性?

是否可以将属性添加到类中,以便将其作为代码而不是在设计器中进行编辑?