13

UITableViewUITextField每个UITableViewCells. 我的 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标签,即使在插入和删除行之后,该标签也会始终正确吗?

对于那些密切关注的人,您可能会认为我的内容.superview太多了,而对于 iOS6,您是对的。但是,在 iOS7 中,单元格的内容视图和单元格本身之间的层次结构中有一个额外的视图(NDA 阻止我详细说明)。这准确地说明了为什么做 superview 的事情有点 hacky,因为它取决于知道如何UITableViewCell实现,并且可能会随着操作系统的更新而中断。

4

4 回答 4

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;
}
于 2013-07-20T02:18:14.380 回答
12

一种更好的方法是遍历视图层次结构,检查每个超级视图是否UITableViewCell使用该class方法。这样,您就不会受到您UITextField和单元格之间的超级视图数量的限制。

类似于以下内容:

UIView *view = field;
while (view && ![view isKindOfClass:[UITableViewCell class]]){ 
    view = view.superview;
}
于 2013-07-20T01:46:05.790 回答
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 出列单元格时重新关联,以确保文本字段与正确的单元格相关联。

于 2013-07-20T01:47:16.663 回答
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];
}

所以现在一个单元格将通过委托方法传递自己和文本。

假设视图控制器已将单元格的委托设置为自身。现在视图控制器将实现一个委托方法。

在视图控制器的实现中:

- (void)tableViewCell:(MyCell *)cell textFieldDidFinishEditingWithText:(NSString *)text
{
    NSIndexPath *indexPath = [_tableView indexPathForCell:cell];
    _list.items[indexPath.row] = text;
}

无论 Apple 如何更改表格视图单元格的视图层次结构,这种方法也将起作用。

于 2013-07-20T02:00:25.180 回答