web-dev-qa-db-fra.com

swift ios ajoute une pagination de défilement infinie à uitableview

Je me demande si tableview a une fonction intégrée pour ajouter un défilement/une pagination infinis.

En ce moment, mon VC ressemble à ceci:

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

Je récupère mes données en utilisant loadSaved (1)} _ en donnant à la fonction la page en cours que je veux charger. La fonction effectue une demande d'API à l'aide d'alomofire, puis renseigne le var data: JSON! = [] Avec les données à afficher.

Donc, ce que je veux faire, c’est que lorsque je fais défiler vers le bas de la vue tableau loadSaved (2)} devrait être appelé charger plus de données dans la vue tableau

11
user2636197

UITableViewDelegate a une méthode d'instance Table View (_: affichera: pour la ligne à:) } qui indique au délégué que la vue de table est sur le point de dessiner une cellule pour une ligne particulière . "

Dans votre cas, je l’utiliserais comme ceci:

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

En fonction de votre code, vous aurez peut-être besoin de quelques vérifications pour vous assurer de ne pas vous retrouver dans une boucle infinie si vous avez chargé toutes vos données ...

21
lukkea

Non, la UITableView n'a pas de fonction intégrée permettant de réaliser le défilement infini ou le chargement de cellules à la demande comme vous le souhaitez. Ce que vous pouvez utiliser est la fonction scrollViewDidScroll(_:) dans la UIScrollViewDelegate implémentée par défaut dans la UITableView et vous permet ainsi de savoir quand l'utilisateur fait défiler plus que la hauteur d'origine définie dans la UITableView.

Par exemple, comme dans ce code:

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

Pour obtenir le résultat de l'ajout du reste des éléments à la fin de la UITableView, vous devez ajouter les nouveaux éléments à la source de données, dans votre cas data à l'intérieur de votre fonction loadSaved(numberOfPage).

J'espère que cela vous aidera. 

4
Victor Sigler

J'ai modifié la réponse de Victor et l'ai utilisée comme,

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

Réinitialisez loadingStatus sur true lorsque vous recevez des données. Sans vérifier si la vue chargeait déjà plus de données, la vue table scintillait.

2
Ravi_sankar

Toutes les réponses ci-dessus sont correctes, mais pour iOS 10 et plus, nous avons une très belle

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

Ceci est un délégué prefetch qui doit être défini 

tableView.prefetchDataSource = self

RayWeinderlich a un bon tutoriel sur le sujet. Puisque Rays est un site fiable, je ne poste pas de code ici

0
amar

Ci-dessus Et ont également raison, mais peut-être que quelqu'un aidera ce code également.

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

La réponse de Ravi est bonne. Mais comme il l’a souligné à la fin, la tableView scintille beaucoup si vous utilisez scrollViewDidScroll(_ scrollView: UIScrollView)

En effet, vous essayez de recharger tableView chaque fois que vous faites défiler tableView. 

À la place, vous pouvez utiliser la méthode déléguée scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) pour déterminer si vous avez suffisamment défilé et si vous avez presque atteint la fin de la 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()
        }

    }
0
iPhoneDeveloper