添加单元格后TableView Auto Scrolling行为不正常

时间:2017-09-20 10:27:43

标签: ios iphone swift uitableview

查看设置:

我的TableView有3个部分,每个部分有4或9个单元格。每个Cell都有一个Label和TextField。 在开始编辑每个部分的索引2处的单元格时,我重新加载现在将包含9个单元格的部分(将模型更新为dequeueCell,以便再添加5个单元格)。

问题:

tableView按预期滚动(将文本字段显示到屏幕的可见部分)以显示该部分的未展开状态。但是在我通过开始编辑任何部分的索引2处的单元格的文本字段来添加单元格之后,tableView会滚动以隐藏文本字段。一旦任何部分扩展了单元格数量,就会对tableview中的任何单元格进行奇怪的滚动。此外,虽然发生了奇怪的滚动,但是重新加载了tableView(这导致焦点远离文本字段)。我已在tableView.reloadSection(_:)单元格的自定义委托中包含didBeginEditing(:_)。 我在iOS 9和10中已经看到了这个问题

对不起解释不好。感谢

继承人Github Repo

问题在这里Problem Demo

P.S。我正在使用Swift 3和Xcode 8.3.3以及部署目标iOS 10

请不要在Swift 4和Xcode 9中建议回答

3 个答案:

答案 0 :(得分:4)

您可以尝试其他方法:更改单元格的高度而不是插入/删除。

更改单元格数以始终返回所有项目:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        guard let sectionEnum = Sections(rawValue: section) else { return 0 }

        return sectionEnum.getRows(forExpanded: true).count
    }

将“隐藏”项目的高度设置为0:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    guard let sectionEnum = Sections(rawValue: indexPath.section) else { return 0 }

    let isExpanded = expandedSectionData[indexPath.section]
    if (!isExpanded) {
        let object = sectionEnum.getRows(forExpanded: true)[indexPath.row]
        if (!sectionEnum.getRows(forExpanded: false).contains(object)) {
            return 0;
        }
    }
    return self.tableView.estimatedRowHeight
}

设置单元格以将子视图剪辑到其边界:

       override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
           ....
           cell.clipsToBounds = true;
           return cell
        }

将更新代码更改为(删除tableView.reloadSections,更改indexPath):

    func didBeginEditing(textField: UITextField, cell: UITableViewCell) {
        guard let indexPath = tableView.indexPath(for: cell), let section = Sections(rawValue: indexPath.section) else { return }
        if indexPath.row == 7 && !expandedSectionData[indexPath.section] {
            expandedSectionData[indexPath.section] = true
            tableView.beginUpdates()
            tableView.endUpdates()
            tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.none, animated: true)
            textField.becomeFirstResponder()
        }

}

答案 1 :(得分:2)

您需要再次将文本字段作为第一响应者,重新加载部分文本字段后不再是第一响应者。

您可能需要更改类似于

的内容
func didBeginEditing(textField: UITextField, cell: UITableViewCell) {
    guard let indexPath = tableView.indexPath(for: cell) else { return }

    if indexPath.row == 2 && !expandedSectionData[indexPath.section] {
        tableView.beginUpdates()
        expandedSectionData[indexPath.section] = true
        tableView.reloadSections(IndexSet(integer: indexPath.section), with: .automatic)
        tableView.endUpdates()

        // after tableview is reloaded, get cell again
        let cell = tableView.cellForRow(at: IndexPath(row: 2, section: indexPath.section)) as? TestCell
        cell?.textField.becomeFirstResponder()
    }
}

我试过这个,看起来很好看。

答案 2 :(得分:2)

此问题与您使用self-sizing tableview cells有关。要解决此问题,请在viewDidLoad中注释掉这两行,并考虑使用tableView定义单元格的高度:heightForRowAtIndexPath:。

chmod a+rx yourscript.sh && sudo mv yourscript.sh /usr/local/bin/yourscript

由于自行调整tableview文档说明,

  

要定义单元格的高度,您需要一个完整的约束链   和视图(具有定义的高度)来填充内容之间的区域   视图的上边缘和下边缘

我也尝试将bottomMargin = textField.bottom约束从优先级750更改为1000,但这并没有解决问题。