简体   繁体   中英

TableView scrolling to top after applying UITableViewDiffableDataSource snapshot

I'm doing pagination using UITableViewDataSourcePrefetching.

The values will be taken from the Realm local storage.

I will get an array of objects. These values will be applied to the existing UITableViewDiffableDataSource datasource.

After applying snapshot the tableview scrolling to the top.

I have verified that all my ChatMessage objects has unique hashValues.

How can I prevent the scrolling?

Link to the video TableView_scroll_issue_video

Given my code snippet

private func appendLocal(chats chatMessages: [ChatMessage]) {
    var sections: [String] = chatMessages.map({ $0.chatDateTime.toString() })
    sections.removeDuplicates()
    guard !sections.isEmpty else { return }
    var snapshot = dataSource.snapshot()
    let chatSections = snapshot.sectionIdentifiers
    sections.forEach { section in
        let messages = chatMessages.filter({ $0.chatDateTime.toString() == section })
        /// Checking the section is already exists in the dataSource
        if let index = chatSections.firstIndex(of: section) {
            let indexPath = IndexPath(row: 0, section: index)
            /// Checking dataSource already have some messages inside the same section
            /// If messages available then add the recieved messages to the top of existing messages
            /// else only section is available so append all the messages to the section
            if let item = dataSource.itemIdentifier(for: indexPath) {
                snapshot.insertItems(messages, beforeItem: item)
            } else {
                snapshot.appendItems(messages, toSection: section)
            }
        } else if let firstSection = chatSections.first {
            /// Newly receieved message's section not available in the dataSource
            /// Add the section before existing section
            /// Add the messages to the newly created section
            snapshot.insertSections([section], beforeSection: firstSection)
            snapshot.appendItems(messages, toSection: section)
        } else {
            /// There is no messages available append the new section and messages
            snapshot.appendSections([section])
            snapshot.appendItems(messages, toSection: section)
        }
    }
    dataSource.apply(snapshot, animatingDifferences: false)
}

You can try the following:

dataSource.applySnapshotUsingReloadData(snapshot, completion: nil)

It's only available from iOS 15.0

You can try creating a new snapshot instead of referencing & mutating the current snapshot of your dataSource.

After looking a bit into it, I realized that you apply the snapshot without animation. That means that on ios versions 13-14 , you are not performing a diff, but actually reloading the data, which means the whole state of the dataSource is lost. Hence the scrolling position is also reset. You need to apply the snapshot with animation on versions 13, 14. There are a few work arounds if you insist on not animating the changes while setting ' animated ' as true , but I don't see, from a UX perspective, why you'd want that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM