如何从一个子视图获取UITableViewCell
我有一个UITableView
中的每个UITextField
。 我有我的ViewController中处理每个单元格的文本字段“退出结束”事件的方法,我想要能够做的是用新的文本更新我的模型数据。
我目前拥有的是:
- (IBAction)itemFinishedEditing:(id)sender { [sender resignFirstResponder]; UITextField *field = sender; UITableViewCell *cell = (UITableViewCell *) field.superview.superview.superview; NSIndexPath *indexPath = [_tableView indexPathForCell:cell]; _list.items[indexPath.row] = field.text; }
当然做field.superview.superview.superview
作品,但它似乎很hacky。 有没有更优雅的方式? 如果我将UITextField
的标签设置为单元格的indexPath.row
,那么在cellForRowAtIndexPath
中的in将使该标签始终正确,即使插入和删除行后也是如此?
对于那些密切关注的人,你可能认为我有一个.superview
太多了,对于iOS6,你会是对的。 但是,在iOS7中,在单元格的内容视图和单元格本身之间的层次结构中有一个额外的视图(NDA阻止我形成详细的表示)。 这正好说明了为什么要做超级视图的事情有点怪异,因为它依赖于知道如何实现UITableViewCell
,并可以与操作系统的更新中断。
既然你的目标是真的获得文本字段的索引path,你可以这样做:
- (IBAction)itemFinishedEditing:(UITextField *)field { [field resignFirstResponder]; CGPoint pointInTable = [field convertPoint:field.bounds.origin toView:_tableView]; NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:pointInTable]; _list.items[indexPath.row] = field.text; }
一个稍微好一点的方法是遍历视图层次结构,检查每个超级视图是否是使用class
方法的UITableViewCell
。 这样,你不受UITextField
和单元格之间的UITextField
视图数量的限制。
有些东西是:
UIView *view = field; while (view && ![view isKindOfClass:[UITableViewCell class]]){ view = view.superview; }
您可以将UITableViewCell
本身作为弱关联附加到UITextField
,然后在UITextFieldDelegate
方法中将其取出。
const char kTableViewCellAssociatedObjectKey;
在你的UITableViewCell子类中:
- (void)awakeFromNib { [super awakeFromNib]; objc_setAssociatedObject(textField, &kTableViewCellAssociatedObjectKey, OBJC_ASSOCIATION_ASSIGN); }
在你的UITextFieldDelegate方法中:
UITableViewCell *cell = objc_getAssociatedObject(textField, &kTableViewCellAssociatedObjectKey); NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; //...
我还build议每次从UITableView出队时重新关联,以确保文本字段与正确的单元格相关联。
基本上在这种情况下,我宁愿将IBAction方法放入单元格而不是视图控制器。 然后当一个动作被触发时,一个单元发送一个委托给一个视图控制器实例。
这里是一个例子:
@protocol MyCellDelegate; @interface MyCell : UITableViewCell @property (nonatomic, weak) id<MyCellDelegate> delegate; @end @protocol MyCellDelegate <NSObject> - (void)tableViewCell:(MyCell *)cell textFieldDidFinishEditingWithText:(NSString *)text; @end
在一个单元的实现中:
- (IBAction)itemFinishedEditing:(UITextField *)sender { // You may check respondToSelector first [self.delegate tableViewCell:self textFieldDidFinishEditingWithText:sender.text]; }
所以现在一个单元格将通过委托方法传递自己和文本。
假设一个视图控制器已经将一个单元格的代理设置为self。 现在一个视图控制器将实现一个委托方法。
在你的视图控制器的实现中:
- (void)tableViewCell:(MyCell *)cell textFieldDidFinishEditingWithText:(NSString *)text { NSIndexPath *indexPath = [_tableView indexPathForCell:cell]; _list.items[indexPath.row] = text; }
无论苹果公司如何改变表格视图单元格的视图层次结构,这种方法也将起作用。