Reputation: 1634
I'm running into an annoying problem. I'm doing a messaging app. In the message page, when the user scrolls to the top, as soon as the topmost cell becomes visible, it will load more messages to display. Because at the time of loading more messages, the position of the table view is at the top (content offset is 0), after done loading messages, I call reloadData
and iOS tries to maintain the offset which consequentially scrolls to the top of the table view again and triggers another load. This is like an infinite loop until there is no more message to load.
I tried to call scrollToRow
right after reloadData
but no luck.
So anything that can keep the table view at the same position (i.e. if before loading, message "a" is at the top, after loading, message "a" still at the top of the screen) after calling reloadData
will work for me.
Spent several hours on this so I'll really appreciate any help. Thanks
Upvotes: 3
Views: 3290
Reputation: 35392
With modern swift you can make it in "one line only" with ternary:
(tableView.indexPathsForVisibleRows)?.isEmpty ?? true ? tableView.reloadData() : tableView.reloadRows(at: tableView.indexPathsForVisibleRows!, with: .none)
Upvotes: 1
Reputation: 236
Don't call reloadData every time when you need to insert just one row; it's bad practice.
UITableView has the method:
func insertRows(at indexPaths: [IndexPath],
with animation: UITableViewRowAnimation)
...and since iOS 11, also:
func performBatchUpdates(_ updates: (() -> Void)?,
completion: ((Bool) -> Void)? = nil)
...which allow you to perform multiple insert, delete, reload, and move operations as a group.
Upvotes: 2
Reputation: 3878
I don't know if this help you but you can try this while reloading-
if let indexPaths = tableView.indexPathsForVisibleRows {
tableView.reloadRows(at: indexPaths, with: .none)
} else {
tableView.reloadData()
}
Upvotes: 4
Reputation: 2082
First update your modelArray and then call reloadData() method of TableView.
It seems you have to implement pagination. Use this method for api call, it will call api once reached at last cell.
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
//Bottom Refresh
if scrollView == yourTableView {
if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height) {
if !isNewDataLoading {
isNewDataLoading = true
apiCall()
}
}
}
}
Make sure you set isNewDataLoading to false once API has responded successfully.
Upvotes: -1