Swift tableView Pagination

Tengo éxito trabajando tableview con json códigos de análisis. Pero puede tener 1000 elementos más, así que necesita paginación cuando se desplaza hacia abajo. No sé cómo puedo hacer esto mis códigos debajo. Para object-c tengo mucho ejemplo pero para swift no encontré el ejemplo de trabajo. Estoy esperando tus ayudas. Creo que será de ayuda a mucha gente. Gracias !

import UIKit class ViewController: UIViewController, UITableViewDataSource,UITableViewDelegate { let kSuccessTitle = "Congratulations" let kErrorTitle = "Connection error" let kNoticeTitle = "Notice" let kWarningTitle = "Warning" let kInfoTitle = "Info" let kSubtitle = "You've just displayed this awesome Pop Up View" @IBOutlet weak var myTableView: UITableView! @IBOutlet weak var myActivityIndicator: UIActivityIndicatorView! var privateList = [String]() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) loadItems() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return privateList.count } internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell:myCell = tableView.dequeueReusableCellWithIdentifier("myCell") as! myCell cell.titleLabel.text = privateList[indexPath.row] return cell } func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { if (editingStyle == UITableViewCellEditingStyle.Delete){ print(indexPath.row) let alert = SCLAlertView() alert.addButton("Hayır"){ } alert.addButton("Evet") { self.myTableView.beginUpdates() self.privateList.removeAtIndex(indexPath.row) tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Left) print("Silindi") self.myTableView.endUpdates() self.loadItems() } alert.showSuccess(kSuccessTitle, subTitle: kSubtitle) } } func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { // the cells you would like the actions to appear needs to be editable return true } override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if(segue.identifier == "Detail") { let destinationView = segue.destinationViewController as! DetailViewController if let indexPath = myTableView.indexPathForCell(sender as! UITableViewCell) { destinationView.privateLista = privateList[indexPath.row] } } } internal func tableView(tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat { return 0.0 } func loadItems() { loadItemsNow("privateList") } func loadItemsNow(listType:String){ myActivityIndicator.startAnimating() let listUrlString = "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString let myUrl = NSURL(string: listUrlString); let request = NSMutableURLRequest(URL:myUrl!); request.HTTPMethod = "GET"; let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in if error != nil { print(error!.localizedDescription) dispatch_async(dispatch_get_main_queue(),{ self.myActivityIndicator.stopAnimating() }) return } do { let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSArray if let parseJSON = json { self.privateList = parseJSON as! [String] } } catch { print(error) } dispatch_async(dispatch_get_main_queue(),{ self.myActivityIndicator.stopAnimating() self.myTableView.reloadData() }) } task.resume() } } 

Para eso necesita tener el lado del servidor cambiar también.

  1. El servidor aceptará fromIndex y batchSize en la URL de API como batchSize de consulta.

     let listUrlString = "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex 
  2. En la respuesta del servidor, habrá una clave adicional totalItems . Esto se usará para identificar todos los artículos recibidos o no. Una matriz o elementos del batchSize al batchSize del batchSize Número de elementos.

En el lado de la aplicación

  1. First loadItem() se llamará con fromIndex = 0 y batchSize = 20 (por ejemplo, en viewDidLoad() o viewWillAppear ). eliminar todos los elementos de la matriz de lista privateList antes de llamar a loadItem() por primera vez

  2. El servidor devuelve una matriz de los primeros 20 elementos y totalItems cantidad total de elementos en el servidor.

  3. Agregue los 20 elementos en la matriz privateList y vuelva a cargar tableView

  4. En el método tableView:cellForRowAtIndexPath , compruebe si la celda es la última. Y compruebe si totalItems (form server) es mayor que privateList.count . Eso significa que hay más elementos en el servidor para cargar

     if indexPath.row == privateList.count - 1 { // last cell if totalItems > privateList.count { // more items to fetch loadItem() // increment `fromIndex` by 20 before server call } } 

Pregunta: ¿ where is refresh ? will be scrolling ? where is refresh ? will be scrolling ?

Actualice después de agregar nuevos elementos en la matriz cuando se reciba la respuesta del servidor. (paso 3)

El desplazamiento activará tableView:cellForRowAtIndexPath para cada celda cuando el usuario se desplaza. El código está comprobando si es la última celda y busca los artículos restantes. (etapa 4)

Proyecto de muestra agregado:
https://github.com/rishi420/TableViewPaging

La forma buena y eficiente de hacerlo es mediante scrollviewDelegate en la vista de tabla. Simplemente agregue UIScrollViewDelegate en su viewController Controlador de vista.

 //For Pagination var isDataLoading:Bool=false var pageNo:Int=0 var limit:Int=20 var offset:Int=0 //pageNo*limit var didEndReached:Bool=false viewDidLoad(_){ tableview.delegate=self //To enable scrollviewdelegate } 

Anular dos métodos de este delegado

 func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { print("scrollViewWillBeginDragging") isDataLoading = false } func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { print("scrollViewDidEndDecelerating") } //Pagination func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { print("scrollViewDidEndDragging") if ((tableView.contentOffset.y + tableView.frame.size.height) >= tableView.contentSize.height) { if !isDataLoading{ isDataLoading = true self.pageNo=self.pageNo+1 self.limit=self.limit+10 self.offset=self.limit * self.pageNo loadCallLogData(offset: self.offset, limit: self.limit) } } } 

Esto ahora es un poco más fácil con la incorporación de un nuevo protocolo en iOS10: UITableViewDataSourcePrefetching

https://developer.apple.com/documentation/uikit/uitableviewdatasourceprefetching

Agregue otra sección a su vista de tabla, permita que esta sección tenga solo 1 fila, que será una celda que contenga un indicador de actividad, para denotar la carga.

 internal func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 2; } internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if section == 0 { return privateList.count } else if section == 1 { // this is going to be the last section with just 1 cell which will show the loading indicator return 1 } } internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { if section == 0 { let cell:myCell = tableView.dequeueReusableCellWithIdentifier("myCell") as! myCell cell.titleLabel.text = privateList[indexPath.row] return cell } else if section == 1 { //create the cell to show loading indicator ... //here we call loadItems so that there is an indication that something is loading and once loaded we relaod the tableview self.loadItems() } } 

SWIFT 3.0 – 4 …

Si está enviando el número de página en la solicitud de la API, esta es la forma ideal para implementar la paginación en su aplicación.

1) declarar la variable Página actual con Valor inicial 0 y un bool para verificar si alguna lista se está cargando con un valor inicial falso

 var currentPage : Int = 0 var isLoadingList : Bool = false 

2) Esta es la función que obtiene el ejemplo de la lista:

  func getListFromServer(_ pageNumber: Int){ self.isloadingList = false self.table.reloadData() } 

3) Esta es la función que incrementa el número de página y llama a la función API

  func loadMoreItemsForList(){ currentPage += 1 getListFromServer(currentPage) } 

4) este es el método que se invocará cuando scrollView se desplace

 func scrollViewDidScroll(_ scrollView: UIScrollView) { if (((scrollView.contentOffset.y + scrollView.frame.size.height) > scrollView.contentSize.height ) && ! isLoadingList){ self. isLoadingList = true self. loadMoreItemsForList() } } 

PD: la función bool isLoadingList es evitar que la vista de desplazamiento obtenga más listas en un arrastre en la parte inferior de la vista de tabla.

Otra forma de hacerlo es: puede establecer un umbral para obtener elementos mientras envía la solicitud cada vez:

Digamos que estás buscando 20 elementos la primera vez. Guardará la última identificación o número de registro recuperado para obtener la lista de los próximos 20 elementos.

 let lastFetchedIndex = 20; 

Supongo que ya ha agregado estos registros en su myArray. MyArray es la fuente de datos de tableView. Ahora myArray contiene 40 objetos. Voy a hacer una lista de indexPaths of rows que debe insertarse en tableView ahora.

 var indexPathsArray = [NSIndexPath]() for index in lastFetchedIndex.. 

Aquí estoy actualizando mi TableView. Asegúrate de que dataSource signifique que tu myArray ya se ha actualizado. Para que pueda insertar las filas correctamente.

 self.tableView.beginUpdates() tableView!.insertRowsAtIndexPaths(indexPathsArray, withRowAnimation: .Fade) self.tableView.endUpdates() 

Necesitaba algo similar en un proyecto y mi solución fue:

1 – crea una variable numberOfObjectsInSubArray (valor inicial 30 o lo que quieras)

2 – crea un subcampo para agregar una cantidad de objetos de tu matriz de lista privada cada vez que toco “mostrar más”

  let subArray = privateList?.subarrayWithRange(NSMakeRange(0, numberOfObjectsInSubArray)) 

Y usarlo en

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

3- Cuando necesites mostrar más objetos, haz:

 func addMoreObjectsOnTableView () { numberOfObjectsInSubArray += 30 if (numberOfObjectsInSubArray < privateList.count) { subArray = privateList?.subarrayWithRange(NSMakeRange(0, numberOfObjectsInSubArray)) } else { subArray = privateList?.subarrayWithRange(NSMakeRange(0, privateList.count)) } tableView.reloadData() } 

Espero que ayude

Aquí hay un código de muestra para la vista de colección:

 var page = 0 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{ print("page Num:\(page)") } func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath){ if arrImagesData.count-1 == indexPath.row && arrImagesData.count%10 == 0{ getMoreImages(page) } } func getMoreImages(page:Int){ //hit api if api_success == true { if self.page == 0 { self.arrImagesData.removeAll() } self.arrImagesData.appendContentsOf(api_data) self.collectionImages.reloadData() self.page = self.page + 1 } }