Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UITableView分页,将无限显示加载_Ios_Swift_Uitableview_Pagination - Fatal编程技术网

Ios UITableView分页,将无限显示加载

Ios UITableView分页,将无限显示加载,ios,swift,uitableview,pagination,Ios,Swift,Uitableview,Pagination,我正在尝试在我的应用程序中实现一个聊天功能,它将模拟iMessages的拉拽来加载更多的消息。我的API在每次调用中发送20条消息以及pageIndex和其他值,以跟踪页面和消息 我正在使用TableView willDisplay和pull来实现分页以刷新功能 我无法添加正确的逻辑以在willDisplay中加载更多消息,它将进入无限循环。有人能通过看下面的代码给我指出正确的方向吗 import UIKit class ChatViewController: UIViewController

我正在尝试在我的应用程序中实现一个聊天功能,它将模拟iMessages的拉拽来加载更多的消息。我的API在每次调用中发送20条消息以及pageIndex和其他值,以跟踪页面和消息

我正在使用TableView willDisplay和pull来实现分页以刷新功能

我无法添加正确的逻辑以在willDisplay中加载更多消息,它将进入无限循环。有人能通过看下面的代码给我指出正确的方向吗

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
            })
        }
    }