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

时间:2018-10-24 16:46:40

标签: ios swift uitableview pagination

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

我正在使用TableView willDisplay实现分页并拉动以刷新功能。

我无法添加正确的逻辑以将更多消息加载到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()
}

}

1 个答案:

答案 0 :(得分:1)

willDisplayCell不是检查tableView是否实际滚动到底部的安全位置,而是使用scrollViewDelegate

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

希望有帮助