web-dev-qa-db-ja.com

swift ios uitableviewに無限スクロールの改ページを追加

Tableviewには、無限のスクロール/ページネーションを追加する組み込み関数があるのでしょうか。

現在、私の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)
}

loadSaved(1)を使用して、関数にロードする現在のページを指定して、データをフェッチします。この関数は、alomofireを使用してAPIリクエストを作成し、表示するデータをvar data:JSON!= []に設定します

だから私がやりたいことは、tableviewの一番下までスクロールするときですloadSaved(2)はもっと多くのデータをtableviewにロードするということです

11
user2636197

UITableViewDelegateには table View(_:will Display:for Row At:)インスタンスメソッド があります。行。"

あなたの場合、私はそれを次のように使用します:

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

コードによっては、すべてのデータをロードした場合に無限ループに陥らないようにするために、これについていくつかのチェックが必要になる場合があります...

22
lukkea

いいえ、UITableViewには、無限スクロールまたはロードオンデマンドセルを実現する組み込み関数はありません。使用できるのは、UIScrollViewDelegateにデフォルトで実装されているUITableViewの関数 scrollViewDidScroll(_:) です。この方法で、ユーザーが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の最後に残りの要素を追加した結果を得るには、新しい要素をデータソースに追加する必要があります。この場合は、関数loadSaved(numberOfPage)内のdataです。

これがお役に立てば幸いです。

5
Victor Sigler

私はビクターの答えを修正し、それをとして使用しました

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がちらつきました。

2
Ravi_sankar

上記の答えはすべて正しいですが、iOS 10以降では非常に良い

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

これは設定が必要なプリフェッチデリゲートです

tableView.prefetchDataSource = self

RayWeinderlich には、このトピックに関する素晴らしいチュートリアルがあります。 Raysは信頼できるサイトなので、ここにコードを投稿していません

2
amar

ラビの答えは良さそうです。しかし、彼が最後に指摘したように、scrollViewDidScroll(_ scrollView: UIScrollView)を使用する場合、tableView flickers

これは、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()
        }

    }
1
iPhoneDeveloper

上記も正しいですが、このコードも助けになるかもしれません。

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
    }
}
0
Vishal Wagh