【问题标题】:Implementing Prev./Next buttons in UITableView to make first responder a UITextField in a non-visible cell在 UITableView 中实现 Prev./Next 按钮以使第一响应者成为不可见单元格中的 UITextField
【发布时间】:2013-04-09 20:08:01
【问题描述】:

在我的应用程序中,每个单元格内都有一个 UITabeViewUITextFields。但是,我在实现上一个/下一个按钮以使上一个/下一个 UITableViewCell 内的文本字段成为第一响应者时遇到了麻烦。

我已经对UITableViewCell 类进行了子类化,让它在按下 prev./next 按钮时调用它的某个方法 delegate 并将单元格本身作为该方法的参数传递(所以我可以得到它的索引路径来计算哪个是单元格的索引路径,其文本字段必须成为第一响应者)

在委托的方法一的实现中:

  • 获取按钮被按下的单元格的索引路径
  • 在该单元格的索引路径中加或减 1(取决于按下的按钮)
  • 使用表格视图上的-cellForRowAtIndexPath: 方法获取必须使其文本字段成为第一响应者的单元格
  • 使文本字段成为第一响应者

问题是-cellForRowAtIndexPath: 方法仅在单元格可见时才返回该单元格。因此,当单元格不可见时,它将返回nil,并且上述算法将不起作用,而当单元格在屏幕上时,它将正常工作。

这是我上一篇的代码。按钮,前提是MUInfoMateriaTableViewCell 是我的UITableViewCell 的子类,并且它有一个textField 属性来返回其文本字段:

- (void)prevButtonPressedInCell:(MUInfoMateriaTableViewCell *)cell
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    NSIndexPath *previousIndexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section];

    MUInfoMateriaTableViewCell *newCell = (MUInfoMateriaTableViewCell *)[self.tableView cellForRowAtIndexPath:previousIndexPath];
    [newCell.textField becomeFirstResponder];
}

有什么方法可以“获取”一个不可见的单元格,以便我可以将其文本字段设置为第一响应者?或者你能建议我另一种算法来解决这个问题吗?

【问题讨论】:

    标签: iphone ios uitableview first-responder


    【解决方案1】:

    您可以通过多步骤流程解决此问题:

    • 跟踪包含所需文本字段的单元格以作为第一响应者
    • 计算要显示的单元格的NSIndexPath 并调用[self.tableView scrollToRowAtIndexPath:atScrollPosition:animated:] 将其显示在视图中
    • 实现tableView:willDisplayCell:forRowAtIndexPath:,以在所需单元格可见且匹配所需单元格或索引路径时调用becomeFirstResponder

    最后一步很重要,因为如果接收者不是任何窗口的子视图,则调用 becomeFirstResponder 不会做任何事情。

    【讨论】:

    • 您建议如何跟踪其文本字段应成为第一响应者的单元格?我是否应该有一个名为 activeCellIndexPath 之类的 ivar,并检查活动单元格的索引路径是否与在 tableView:willDisplayCell:forRowAtIndexPath: 中作为参数传递的单元格的索引路径匹配,还是有更好/更有效的方法?
    • 我会按照你刚才描述的方式实现。请务必处理您不想让任何单元格成为响应者和nil out activeCellIndexPath 的情况。
    【解决方案2】:

    使用scrollToRowAtIndexPath:atScrollPosition:animated:滚动表格视图,使单元格可见。

    例如

    - (void)prevButtonPressedInCell:(MUInfoMateriaTableViewCell *)cell
    {
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
        NSIndexPath *previousIndexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section];
    
        [self.tableView scrollToRowAtIndexPath:previousIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
    
        MUInfoMateriaTableViewCell *newCell = (MUInfoMateriaTableViewCell *)[self.tableView cellForRowAtIndexPath:previousIndexPath];
        [newCell.textField becomeFirstResponder];
    }
    

    【讨论】:

      【解决方案3】:

      问题是 -cellForRowAtIndexPath: 方法返回 仅当单元格可见时。

      这是因为当其行不可见时,该单元格不存在。 UITableView 只保留绘制表格所需的那些单元格。这就是为什么当您滚动表格时会收到大量-tableView:cellForRowAtIndexPath: 消息的原因——表格要求其数据源提供它没有的单元格。

      如果您想使用当前的方法,您需要滚动表格,以便将要编辑的行变得可见,如 Gabriele Petronella 的回答所示。

      【讨论】:

      • 这是错误的。查看tableView:cellForRowAtIndexPath: 的典型实现,您会看到会发生什么。它总是返回一个单元格,但如果它当前不可见,它可能必须为该索引路径构建一个新单元格。或者它可能仍将其保存在其单元缓存中,在这种情况下,它将出列并返回已经存在的单元。
      • @Logachu 我的回答在原始问题的上下文中是正确的,但是不正确的编辑将-cellForRowAtIndexPath:(一种UITableView 方法)更改为-tableView:cellForRowAtIndexPath:(一种UITableViewDataSource 方法),从而改变了问题。这肯定发生在我回答的大约同一时间,因为我将不正确的文本复制到了我的回答中的引用中。我已经修正了报价和问题,如果您在阅读我的回答时考虑到 UITableView(也许检查the docs),我希望您同意它是正确的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-30
      • 1970-01-01
      • 1970-01-01
      • 2017-09-10
      • 1970-01-01
      相关资源
      最近更新 更多