使用自定义 UITableViewCell 时在编辑之前更改 UITextField 文本

Posted

技术标签:

【中文标题】使用自定义 UITableViewCell 时在编辑之前更改 UITextField 文本【英文标题】:Change UITextField text right before editing when using custom UITableViewCell 【发布时间】:2012-03-27 18:48:41 【问题描述】:

我在这里遇到了一个奇怪的问题。我有一个使用自定义 UITableViewCells 的 UITableView。除了在特定问题上之外,一切都按预期工作。

这是场景:

我需要在编辑开始之前删除 UITextField 中的“$”符号。这是通过textFieldShouldBeginEditing: 方法完成的。

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField 
    LifeEarningsLineItemTableViewCell *cell = (LifeEarningsLineItemTableViewCell *)[self tableViewCellContainingObject:textField inTableView:self.lifeEarningsTableView];
    if (textField == cell.itemAmount) 
        /*Remove currency symbol for editing.*/
        NSString *currencySymbol = [self.currencyFormatter currencySymbol];
        NSMutableString *mutableText = [NSMutableString stringWithString:textField.text];
        [mutableText replaceOccurrencesOfString:currencySymbol withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableText length])];
        textField.text = mutableText;
    

    return YES;
  

问题来了:

不同 行之间,从 textField1 移动到 textField2(在不同的行中),“$”删除,这是 GOOD . 在同一行中,从 textField1 移动到 textField2,“$”没有被删除,这是 BAD

为什么“$”不是在同一行中被删除,而是在不同的行中删除?

这是问题的直观表示:

[编辑...添加] 我通过这些流程获得了这些日志:

应该开始.....行:0,标签:0 应该开始.....行:0,标签:1 DID END .....行:0,标签:0 DID END .....行:0,标签:1

应该开始.....行:0,标签:0 应该开始.....行:1,标签:1 DID END .....行:0,标签:0 DID END .....行:1,标签:1

另外,这里是tableViewCellContainingObject:inTableView:tableView 方法:

- (UITableViewCell *)tableViewCellContainingObject:(UIView *)view inTableView:(UITableView *)tableView 
    CGPoint objectRectInTableViewCoordinates = [tableView convertPoint:view.bounds.origin fromView:view];
    NSIndexPath *cellIndexPath = [tableView indexPathForRowAtPoint:objectRectInTableViewCoordinates];
    return [tableView cellForRowAtIndexPath:cellIndexPath];

还有textFieldDidEndEditing 方法:

- (void)textFieldDidEndEditing:(UITextField *)textField 
    LifeEarningsLineItemTableViewCell *cell = (LifeEarningsLineItemTableViewCell *)[self tableViewCellContainingObject:textField inTableView:self.lifeEarningsTableView];
    LifeEarningsLineItem *lifeEarningsLineItem = [self.lifeEarningsFetchedResultsController objectAtIndexPath:[self.lifeEarningsTableView indexPathForCell:cell]];

    if (textField == cell.itemAmount) 
        NSNumber *absInteger = [NSNumber numberWithInteger:abs([textField.text integerValue])];
        textField.text = [self.currencyFormatter stringFromNumber:absInteger];
        lifeEarningsLineItem.amount = absInteger;
        [self sumAmountsAndDisplay];
     else if (textField == cell.itemName) 
        lifeEarningsLineItem.name = textField.text;
    

【问题讨论】:

好吧,唯一的可能是由于某种原因(您没有显示它的代码)tableViewCellContainingObject: inTableView: 在发生这种情况时没有返回正确的单元格。 我通过indexPathForCell: 的日志语句检查了这一点。它不仅记录了正确的行,还通过theTextField.text 记录了那些 UITextFields 的正确值。从上面的代码中,当我登录textField.text 时,它实际上记录了正确的文本(没有“$”)!然而,它在视觉上显示了“$”符号。仅供参考,这是通过模拟器(ios 5.1)。 如果您记录 textField.text 并显示正确的值,是否会从不同的行中删除 $? 好吧,当你改变文本时 UITextField 会刷新它的视图.... 所以我猜你是用textFieldShouldEndEditing 重新添加$?真的,唯一有意义的是它作用于错误的行,当它在错误的行上结束编辑时,它会重新添加 $ 。打破这两个函数,看看它们在什么时候被调用了多少次你试一下。我猜当你直接穿过时,你会得到一个结束,然后是一个开始,但是当你切换时,你会得到一个结束,一个开始和一个结束。 【参考方案1】:

我认为您的解决方案(在编辑期间解耦 FRC)可能有点过激,并且可能会产生无法预料的影响。这里有几个替代建议。我假设问题是由于表格在您完成编辑单元格中的第一个字段后重新加载您正在编辑的行引起的。

不要在模型中存储货币符号,将其添加到 cellForRowAtIndexPath 中显示的文本中,如果文本字段未编辑。当您的文本字段开始编辑时,将其文本设置为直接来自模型的值。您不必在结束编辑中做任何事情,因为重新加载会为您重新添加货币符号。 如果您不想更改模型,无论如何您都可以执行类似的操作 - 如果单元格正在编辑,请在 cellForRowAtIndexPath 中删除货币符号。 存储当前编辑行的索引路径,并在 FRC 委托方法中有条件地忽略对此行的更改。

【讨论】:

特别是第一个要点。我已经将一个 NSNumber 存储到我的模型中(即没有保存 $ )。但是建议“将其添加到 cellForRowAtIndexPath 中显示的文本中,if 文本字段未编辑”,if 是一个不错的简单方法.我完全忽略了这是一个检查文本字段是否正在编辑的好地方。所以在我的configureCell(在cellForRowAtIndexPath 中调用)中,新编辑的行:if (lifeEarningsLineItemCell.itemAmount.editing == NO) lifeEarningsLineItemCell.itemAmount.text = [self.currencyFormatter stringFromNumber:lifeEarningsLineItem.amount];。谢谢。 乐于助人。我知道整天盯着一个问题却错过一个明显的解决方案是什么感觉!【参考方案2】:

好的,我发现了问题...这是该死的 NSFetchedResultsController 委托方法,特别是 NSFetchedResultsChangeUpdate 更改类型。这不是NSFetchedResultsController 第一次走遍我的桌子。我应该记得NSFetchedResultsController 不适合用户驱动的编辑。

所以这就是我解决问题的方法(但我仍然担心整个事情都会崩溃):

因为事件的先后顺序……

SHOULD BEGIN.....Row:0, Tag:0  
SHOULD BEGIN.....Row:0, Tag:1  
DID END.....Row:0, Tag:0  
DID END.....Row:0, Tag:1  

...我不能只使用BOOL 属性来表示文本字段处于编辑模式(事件的顺序必须是 BEGIN->END->BEGIN->END)。

所以我创建了属性:@property (nonatomic, strong) NSMutableSet *stackOfEditingTextFields;

然后在textFieldShouldBeginEditing:方法的开头,我添加了:

/*Add text field to stack of editing text fields and disable the fetched results controller delegate.*/
[self.stackOfEditingTextFields addObject:textField];
self.lifeEarningsFetchedResultsController.delegate = nil;

然后在textFieldDidEndEditing:方法的最后,我加了:

/*Remove text field from stack of editing text fields. If stack count is 0, reengage the fetched results controller delegate.*/
[self.stackOfEditingTextFields removeObject:textField];
if ([self.stackOfEditingTextFields count] == 0) self.lifeEarningsFetchedResultsController.delegate = self;

如果有更好的建议或我没有看到的任何不可预见的副产品错误,我会全力以赴。

感谢 lnafziger 的帮助,帮助我完成它,并提出不同的角度(我为你的 cmets +1 了)。

【讨论】:

很高兴您解决了这个问题,但我同意您对解决方案的担忧。如果您在编辑期间离开应用程序或切换到另一个选项卡会发生什么情况,键盘会关闭并且 FRC 代表会重新连接吗?

以上是关于使用自定义 UITableViewCell 时在编辑之前更改 UITextField 文本的主要内容,如果未能解决你的问题,请参考以下文章

在自定义 UITableViewCell 上使用图像时 IOS 8 崩溃

自定义uitableviewcell时,registerNib与registerClass的区别(转载)

在 iOS 中使用自定义单元格时无法查看 UITableViewCell

在运行时无法更改和自定义自定义 UITableViewCell 中的 UIButtons 的标题

编辑时尝试使用 UITextField 制作自定义 UITableViewCell becomeFirstResponder

注册自定义 uitableviewcell 时出错