簡體   English   中英

UITableView InfiniteScrolling 無需在 Swift 中重新加載 TableView

[英]UITableView InfiniteScrolling without reloading TableView in Swift

我正在嘗試使用 UITableView 中的分頁 API 實現無限滾動。 因此,當到達底部單元格並重新加載整個 UITableView 時,我正在更新模型(再次調用 API 並附加結果)。 我面臨的問題是,當重新加載完成時,我看到屏幕上閃爍,但我只想以平滑的方式在 tableView 中添加更多單元格而沒有任何閃爍。 這是我為此寫的:

class FeedViewController: UIViewController {    
    @IBOutlet private weak var tableView: UITableView!
    private var feed: Feed!

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        feed = Feed(delegate: self)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        feed.fetch(nextPage: true)
    }
}

//MARK: TableView
extension FeedViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return feed.articles.count + 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row < feed.articles.count {
            guard let cell = tableView.dequeueReusableCell(withIdentifier: "FeedTableViewCell") as? FeedTableViewCell else {
                return UITableViewCell()
            }
            cell.delegate = self
            cell.setCell(article: feed.articles[indexPath.row])
            return cell
        }
        else if feed.articles.count > 0 && !feed.hasReachedEnd {
            guard let cell = tableView.dequeueReusableCell(withIdentifier: "LoaderTableViewCell") as? LoaderTableViewCell else {
                return UITableViewCell()
            }
            cell.addLoader()
            return cell
        }
        return UITableViewCell()
    }
}

extension FeedViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if indexPath.row == feed.articles.count && !feed.hasReachedEnd {
            feed.fetch(nextPage: true)
        }
    }
}

//MARK: API Management
extension FeedViewController: FeedProtocol {
    func requestCompletedSuccessfully() {
        DispatchQueue.main.async { [weak self] in
            self?.loader.stopAnimating()
            self?.tableView.reloadData()
        }
    }

    func requestFailedWith(error: NSError?) {}
}

在這里您可能會看到,一旦獲取請求完成,我就會使用委托在那里重新加載整個 tableView,但如果可能的話,我需要一些更好的解決方案來避免這種閃爍。 如果還需要其他東西,請告訴我。 謝謝

你應該做的是調用tableView.reloadRows而不是tableView.reloadData 但是為了做到這一點,您需要知道當 requestCompletedSuccessfully 執行時您的提要中有多少新元素。 就像是:

let indexPaths = Array(previousFeedCount..<newFeedCount)
    .map { IndexPath(row: $0, section: 0) }
tableView.reloadRows(at: indexPaths, with: .automatic)

只需使用scrollView Delegate,tableview 默認繼承自UIScrollView 並將delegate 設置為self。

extension FeedViewController: UIScrollViewDelegate {
       func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

        if self.tableView.contentOffset.y <= -10  {

            // table view reached top place your pull to refresh call here
        } else if ((tableView.contentOffset.y + tableView.frame.size.height) >= tableView.contentSize.height) {
            //table view reached last record, fetch next records here
            // tableview usually flickers if content to be reloaded is out of screen bounds. There is one hack to avoid that, add replace these three lines with tableView.reloadData() line
            UIView.setAnimationsEnabled(false)
            tableView.reloadData()
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                UIView.setAnimationsEnabled(true)
            }
       }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM