Ios UITableView分页,将无限显示加载
我正在尝试在我的应用程序中实现一个聊天功能,它将模拟iMessages的拉拽来加载更多的消息。我的API在每次调用中发送20条消息以及pageIndex和其他值,以跟踪页面和消息 我正在使用TableView willDisplay和pull来实现分页以刷新功能 我无法添加正确的逻辑以在willDisplay中加载更多消息,它将进入无限循环。有人能通过看下面的代码给我指出正确的方向吗Ios UITableView分页,将无限显示加载,ios,swift,uitableview,pagination,Ios,Swift,Uitableview,Pagination,我正在尝试在我的应用程序中实现一个聊天功能,它将模拟iMessages的拉拽来加载更多的消息。我的API在每次调用中发送20条消息以及pageIndex和其他值,以跟踪页面和消息 我正在使用TableView willDisplay和pull来实现分页以刷新功能 我无法添加正确的逻辑以在willDisplay中加载更多消息,它将进入无限循环。有人能通过看下面的代码给我指出正确的方向吗 import UIKit class ChatViewController: UIViewController
import UIKit
class ChatViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {
@IBOutlet weak var messagesTable: UITableView!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
var messages: Messages!
var messageArray = [Message]()
// Pagination
var isLoading = false
var pageSize = 10
var totalPages: Int!
var currentPage: Int!
// Pull To Refresh
let refreshControl = UIRefreshControl()
override func viewWillAppear(_ animated: Bool){
super.viewWillAppear(animated)
activityIndicator.startAnimating()
fetchMessages(page: 1, completed: {
self.totalPages = self.messages.pageCount
self.currentPage = self.messages.currentPage
// Sort message by ID so that latest message appear at the bottom.
self.messageArray = self.messages.messages!.sorted(by: {$0.id! < $1.id!})
self.messagesTable.reloadData()
// Scroll to the bottom of table
self.messagesTable.scrollToBottom(animated: false)
self.activityIndicator.stopAnimating()
})
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messageArray.count
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if !self.isLoading && indexPath.row == 0 {
self.isLoading = true
fetchMessages(page: self.currentPage, completed: {
if self.currentPage == 0 {
self.messageArray.removeAll()
}
self.messageArray.append(contentsOf: self.messages!.messages!)
self.messageArray = self.messageArray.sorted(by: {$0.id! < $1.id!})
self.messagesTable.reloadData()
// Scroll to the top
self.messagesTable.scrollToRow(at: indexPath, at: UITableViewScrollPosition.top, animated: true)
self.currentPage = self.currentPage + 1
})
self.isLoading = false
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as? MessageCell else {
fatalError("Can't find cell")
}
return cell
}
private func fetchMessages(page: Int, completed: @escaping () -> ()){
guard let url = URL(string: "http://example.com/....") else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print("Error in fetching data..........")
print(error!.localizedDescription)
}
guard let data = data else { return }
if let str = String(data: data, encoding: .utf8) { print(str) }
do {
let resultData = try JSONDecoder().decode(messagesStruct.self, from: data)
DispatchQueue.main.async {
print("DispatchQueue.main.async")
self.messages = resultData.data!
completed()
}
} catch let jsonError {
print(jsonError)
}
}.resume()
}
//Pull to refresh
@objc func refresh(_ refreshControl: UIRefreshControl) {
fetchMessages(completed: {
self.messagesTable.reloadData()
})
refreshControl.endRefreshing()
}
}willDisplayCell不是检查tableView是否实际滚动到底的安全位置,而不是使用scrollViewDelegate
希望对你有帮助,我已经试过了。第一个问题是,scrollViewDidScroll在调用任何viewXYZAppear方法之前就被调用了,并进入fetch&reload表。这正常吗?@davems:我个人更喜欢这样,而不是手动调用fetchMessagespage:1,在ViewWillDisplay中,但很难相信,当tableView中没有数据时,messagesTable.contentOffset.y>=messagesTable.contentSize.height-messagesTable.frame.size.height条件将永远存在pass@davems:但如果出于任何奇怪的原因发生这种情况,它将使您不再手动调用fetchMessagespage:1,哪一个更干净:这有点像创建自启动加载机制:但我几乎不怀疑如果它没有内容开始,scrollViewDidScroll是否会被调用,即使它被调用,我也非常怀疑它是否会通过条件。在调用任何viewXXXApepar之前,请放置一个断点并再次检查这是第一次打印:isLoading:false messagesTable.contentOffset.y:0.0 messagesTable.contentSize.height:0.0 messagesTable.frame.size.height:590.0条件变为真。@davems:hmmmm有意思,请给我一秒钟:但请相信我评论一下您的评论viewwillfetchmessagespage:1,您将看到您有一个很好的分页系统,它会自动启动:P尽管在那之前启动本身并不是目的,让我检查一下我是如何解决它的
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if !self.isLoading && (messagesTable.contentOffset.y >= (messagesTable.contentSize.height - messagesTable.frame.size.height)) {
self.isLoading = true
fetchMessages(page: self.currentPage, completed: {[weak self]
guard let strongSelf = self else {
return
}
strongSelf.isLoading = false
if strongSelf.currentPage == 0 {
strongSelf.messageArray.removeAll()
}
strongSelf.messageArray.append(contentsOf: strongSelf.messages!.messages!)
strongSelf.messageArray = strongSelf.messageArray.sorted(by: {$0.id! < $1.id!})
strongSelf.messagesTable.reloadData()
strongSelf.currentPage = strongSelf.currentPage + 1
})
}
}