将行插入UITableView的顶部会导致行向下移动,从而导致错误的动画

时间:2018-04-24 18:01:47

标签: ios swift uitableview uikit

我的应用程序的行为类似于典型的消息应用程序。

让我们说用户有100条消息,我的页面大小为20.当用户登陆页面时,我会显示最后一页(消息来自80 - 100)。

当用户向上滚动时,我会在willDisplay的indexPath变为indexPath.row = 0 && indexPath.section = 0时获取上一页(60 - 80)。我构建了dataSource数组并调用insertRows:at:with:。我遇到的问题是,当我插入行时,它从indexPath.row = 0 && indexPath.section = 0开始,这导致它触发前一页的预取,导致其余页面的过早预取。我可以有一个标志来避免这种情况,但它仍然会推动其余的单元格,导致它松开滚动位置,然后返回导致闪烁的动画。

我使用rowHeight = UITableViewAutomaticDimension计算单元格高度。

我已尝试拨打scrollToRow(at:at:animated),但在insertRows:被调用时仍然会向下推。

我知道这在理论上是可行的,因为像Whatsapp和iMessage这样的应用程序有这种行为(假设他们使用tableView)并且它们运行良好。

以下是我所拥有的要点:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if !insertingRows && indexPath.section == 0 && indexPath.row == 0 {
        loadData()
    }
}

private func loadData() {
    dataSource.load({ [weak self] (success: Bool, error: Error?) in
        guard let strongSelf = self else {
            return
        }

        let newMessagesCount = 20 // testing
        var indices = [IndexPath]()
        for index in stride(from: 0, to: newMessagesCount, by: 1) {
            indices.append(IndexPath(row: index, section: 0))
        }

        DispatchQueue.main.async {
            strongSelf.insertingRows = true
            UIView.setAnimationsEnabled(false)
            strongSelf.tableView.insertRows(at: indices, with: .none)
            UIView.setAnimationsEnabled(true)
            strongSelf.insertingRows = false
        }
    })
}

1 个答案:

答案 0 :(得分:0)

您可以只将元素添加到数据源,而不是使用tableView的插入行功能。然后,您可以使用以下代码替换DispatchQueue.main.async函数中的代码。

let oldContentHeight: CGFloat = tableView.contentSize.height
let oldOffsetY: CGFloat = tableView.contentOffset.y
tableView.reloadData()
let newContentHeight: CGFloat = tableView.contentSize.height
tableView.contentOffset.y = oldOffsetY + (newContentHeight - oldContentHeight)

查看我发现的这个要点以获取更多信息: https://gist.github.com/WorldDownTown/9ed681148e9224f7157c9e8620ce46b8