UITableView
每个UITextField
都有一个UITableViewCells
。我在我的ViewController中有一个方法,它处理每个单元格的文本字段的“Do End On Exit”事件,我希望能够用新文本更新我的模型数据。
我目前拥有的是:
- (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
有效,但它看起来很丑陋。有更优雅的方式吗?如果我将UITextField
的标记设置为indexPath.row
中的cellForRowAtIndexPath
,那么即使在插入和删除行后,该标记是否仍然正确?
对于那些密切关注的人,你可能会认为我有一个.superview
太多,对于iOS6,你是对的。但是,在iOS7中,在单元格的内容视图和单元格本身之间的层次结构中有一个额外的视图(NDA阻止我形成详细说明)。这恰恰说明了为什么做superview的事情有点hacky,因为它取决于知道如何实现UITableViewCell
,并且可以打破操作系统的更新。
答案 0 :(得分:31)
由于您的目标是获取文本字段的索引路径,因此您可以这样做:
- (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;
}
答案 1 :(得分:12)
执行此操作的一种稍微好一点的方法是遍历视图层次结构,使用UITableViewCell
方法检查每个超级视图是否为class
。这样,您就不会受到UITextField
和单元格之间的超级视图数量的限制。
有些事情:
UIView *view = field;
while (view && ![view isKindOfClass:[UITableViewCell class]]){
view = view.superview;
}
答案 2 :(得分:3)
您可以将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];
//...
我还建议每次将单元格从UITableView中取出时重新关联,以确保文本字段与正确的单元格相关联。
答案 3 :(得分:1)
基本上在这种情况下,我希望您将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;
}
无论Apple如何更改表格视图单元格的视图层次结构,此方法也会起作用。