簡體   English   中英

swift ios 添加無限滾動分頁到 uitableview

[英]swift ios add infinite scroll pagination to uitableview

我想知道 tableview 是否有任何內置的 function 來添加無限滾動/分頁。

現在我的 VC 看起來像這樣:

var data: JSON! = []

override func viewDidLoad() {
    super.viewDidLoad()

    //Init start height of cell
    self.tableView.estimatedRowHeight = 122
    self.tableView.rowHeight = UITableViewAutomaticDimension

    self.tableView.delegate = self
    self.tableView.dataSource = self

    savedLoader.startAnimation()
    //Load first page
    loadSaved(1)

}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return data.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("aCell") as! SavedTableViewCell

    let info = data[indexPath.row]
    cell.configureWithData(info)

    return cell
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    performSegueWithIdentifier("WebSegue", sender: indexPath)

    tableView.deselectRowAtIndexPath(indexPath, animated: false)
}

我通過為 function 提供我要加載的當前頁面來使用loadSaved(1)獲取我的數據。 function 使用 alomofire 發出 API 請求,然后填充var 數據:JSON! = []包含應顯示的數據

所以我想做的是當我滾動到 tableview 的底部時應該調用loadSaved(2)將更多數據加載到 tableview

UITableViewDelegate 有一個 tableView (_: will Display: for Row At: ) 實例方法,它“告訴委托 table view 即將為特定行繪制一個單元格。”

在你的情況下,我會像這樣使用它:

override open func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if indexPath.row == data.count-1 { //you might decide to load sooner than -1 I guess...
      //load more into data here
    }
}

根據您的代碼,您可能需要對此進行一些檢查,以確保在您加載了所有數據后不會陷入無限循環......

不, UITableView沒有任何內置函數來實現無限滾動或按需加載單元格。 您可以使用的是UIScrollViewDelegate的函數scrollViewDidScroll(_:)UITableView默認實現,這樣就知道用戶何時滾動超過UITableView定義的原始高度。

例如像在這段代碼中:

var indexOfPageToRequest = 1

override func scrollViewDidScroll(scrollView: UIScrollView) {

    // calculates where the user is in the y-axis
    let offsetY = scrollView.contentOffset.y
    let contentHeight = scrollView.contentSize.height

    if offsetY > contentHeight - scrollView.frame.size.height {

        // increments the number of the page to request
        indexOfPageToRequest += 1

        // call your API for more data
        loadSaved(indexOfPageToRequest)

        // tell the table view to reload with the new data
        self.tableView.reloadData()
    }
}

為了實現在結尾處添加元素的其余部分的結果UITableView你應該添加新的元素到數據源,在你的情況下data的函數中loadSaved(numberOfPage)

我希望這對你有幫助。

以上所有答案都是正確的,但對於 iOS 10 及更高版本,我們有一個非常好的

func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath])

這是一個需要設置的預取委托

tableView.prefetchDataSource = self

RayWeinderlich有一個關於這個主題的不錯的教程。 由於 Rays 是一個可靠的網站,我不會在這里發布代碼

我修改了維克多的答案並將其用作,

var indexOfPageRequest = 1
var loadingStatus = false

func loadData(){
    if !loadingStatus{
        loadingStatus = true
        viewModel.getData(pageIndex: indexOfPageRequest)
    }
}

override func scrollViewDidScroll(_ scrollView: UIScrollView) {

    // calculates where the user is in the y-axis
    let offsetY = scrollView.contentOffset.y
    let contentHeight = scrollView.contentSize.height

    if offsetY > contentHeight - scrollView.frame.size.height {

        // increments the number of the page to request
        indexOfPageRequest += 1

        // call your API for more data
        loadData()

        // tell the table view to reload with the new data
        self.tableView.reloadData()
    }
}

接收數據時將 loadingStatus 重置為 true。 沒有檢查視圖是否已經加載了更多數據,tableview 正在閃爍。

首先,創建一個帶有Xib文件的UITableViewCell並在單元格的中心添加一個UIActivityIndicatorView

然后, Control+left click並將UIActivityIndicatorView拖到您的 .swift 文件中,並命名為activityIndicator ……並添加“ loadingcellid ”作為Identifier

現在,讓我們進入我們有UITableView TableViewController ,並在viewDidLoad()注冊加載單元。

override func viewDidLoad() {
    super.viewDidLoad()
    //...
    
    //Register Loading Cell
    let tableViewLoadingCellNib = UINib(nibName: "LoadingCell", bundle: nil)
    self.tableView.register(tableViewLoadingCellNib, forCellReuseIdentifier: "tableviewloadingcellid")
}

UITableView's委托和數據源中,我們在numberOfRowsInSection方法中添加以下代碼。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0 {
        //Return the amount of items
        return itemsArray.count
    } else if section == 1 {
        //Return the Loading cell
        return 1
    } else {
        //Return nothing
        return 0
    }
}

..我們返回 2 個部分(一個用於項目,一個用於Loading Cell )。

  func numberOfSections(in tableView: UITableView) -> Int {
        return 2
    }

cellForRowAt方法中,我們返回每個部分的單元格:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.section == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewitemcellid", for: indexPath) as! TableViewItemCell
            cell.itemLabel.text = itemsArray[indexPath.row]
            return cell
        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: 
       "tableviewloadingcellid", for: indexPath) as! TableViewLoadingCell
            cell.activityIndicator.startAnimating()
            return cell
        }
    }

...我們還設置了行height

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath.section == 0 {
        return 44 //Item Cell height
    } else {
        return 55 //Loading Cell height
    }
}

接下來,我們使用方法scrollViewDidScroll ,來自UITableView嵌入的UIScrollView ,來檢測用戶何時接近列表末尾以調用該方法......

 var isLoading = false

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let offsetY = scrollView.contentOffset.y
        let contentHeight = scrollView.contentSize.height

        if (offsetY > contentHeight - scrollView.frame.height * 4) && !isLoading {
            loadMoreData()
        }
    }

... loadMoreData() 下載更多數據。

func loadMoreData() {
    if !self.isLoading {
        self.isLoading = true
        DispatchQueue.global().async {
            // Fake background loading task for 2 seconds
            sleep(2)
            // Download more data here
            DispatchQueue.main.async {
                self.tableView.reloadData()
                self.isLoading = false
            }
        }
    }
}

它運行良好,形成更多:- https://johncodeos.com/how-to-add-load-more-infinite-scrolling-in-ios-using-swift/

在此處輸入圖片說明

拉維的回答看起來不錯。 但正如他最后指出的那樣,如果您使用scrollViewDidScroll(_ scrollView: UIScrollView) ,tableView 會閃爍很多

這是因為您每次滾動 tableView 時都試圖重新加載 tableView。

相反,您可以使用scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool)委托方法來確定您是否已經足夠滾動並幾乎到達 tableView 的末尾。

override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

    let offsetY = scrollView.contentOffset.y
        let contentHeight = scrollView.contentSize.height

        if offsetY > contentHeight - scrollView.frame.size.height {
               indexOfPageRequest += 1
               loadData()
               self.tableView.reloadData()
        }

    }

上面的 Ans 也是對的,但也可能有人幫助解決此代碼。

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath){
    if(indexPath.row == self.arryOfData.count-1){
        if(self.pageNumber <= self.resPgNumber){
            if(remaining != 0){
                let spinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
                spinner.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(44))
                spinner.startAnimating()
                tableView.tableFooterView = spinner
                tableView.tableFooterView?.isHidden = false

                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                    self.flgActivity = false
                    self.getActiveOrdersList()
                }
            }
            else{
                tableView.tableFooterView?.removeFromSuperview()
                let view = UIView()
                view.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(5))
                tableView.tableFooterView = view
                tableView.tableFooterView?.isHidden = true
            }
        }
        else{
            tableView.tableFooterView?.removeFromSuperview()
            let view = UIView()
            view.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(5))
            tableView.tableFooterView = view
            tableView.tableFooterView?.isHidden = true
        }
    }
    else{
        tableView.tableFooterView?.removeFromSuperview()
        let view = UIView()
        view.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(5))
        tableView.tableFooterView = view
        tableView.tableFooterView?.isHidden = true
    }
}

我們有很多方法可以做到這一點。 所有不同方式的本質是當用戶滾動到最后一組時加載下一組數據。 我通過在 tableView 的末尾添加一個額外的特殊單元格來實現它,當該單元willDisplay cell: forRowAtIndexPath:載到willDisplay cell: forRowAtIndexPath:觸發下一組數據獲取。

雖然這很容易實現,但在較大的應用程序中,有時我們需要在很多地方實現它。 為了避免這種情況,我編寫了一個非侵入性且易於集成的小框架

暫無
暫無

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

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