2016-02-12 17 views
18

Ho un buon successo con tableview con i codici jSON parsing. Ma potrebbe avere 1000 oggetti in più, quindi è necessario impaginare scorrendo il lato inferiore. Non so come posso fare questo i miei codici sotto sotto. Per l'obiettivo-c ho un sacco di esempi ma per il rapido non ho trovato un esempio funzionante. Sto aspettando il tuo aiuto. Penso che aiuterà troppe persone. Grazie !Tavola rapidaVisualizzazione paginazione

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


} 
+0

State recupero migliaio di oggetti alla volta? –

+0

@ShehzadAli no, ma è necessario aggiornare i nuovi quando lo scorrimento in basso sarà buono. Anche molti oggetti richiederanno molto tempo. – SwiftDeveloper

risposta

28

Per questo è necessario anche il cambio di lato del server.

  1. Server accetterà fromIndex e batchSize nel API URL come interrogazione param.

    let listUrlString = "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex 
    
  2. Nella risposta del server, ci sarà una chiave supplementare totalItems. Questo verrà utilizzato per identificare tutti gli articoli ricevuti o meno. Un array o articoli da fromIndex a batchSize numero di elementi.

Nel lato app

  1. Prima loadItem() sarà chiamato con fromIndex = 0 e batchSize = 20 (per esempio in viewDidLoad() o viewWillAppear). RemoveAll elementi da privateList serie prima di chiamare loadItem() per la prima volta

  2. Server restituisce un array di 20 elementi primi e totalItems numero totale di elementi nel server.

  3. aggiungere i 20 elementi in privateList matrice e ricaricare tableView

  4. In tableView:cellForRowAtIndexPath metodo di controllo se la cella è l'ultima cella. E verificare se totalItems (server di moduli) è maggiore di privateList.count.Ciò significa che ci sono più elementi nel server per caricare

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

Domanda:where is refresh ? will be scrolling ?

Refresh dopo aggiungendo nuovi elementi nella matrice quando risposta del server ricevuto. (passaggio 3)

Lo scorrimento attiverà tableView:cellForRowAtIndexPath per ogni cella quando l'utente scorre. Il codice sta controllando se è l'ultima cella e recupera gli oggetti rimanenti. (Fase 4)

progetto Campione aggiunto:
https://github.com/rishi420/TableViewPaging

+0

dove viene aggiornato? scorrerà? – SwiftDeveloper

+0

puoi scrivere codice completo codice completo integrato che testerò – SwiftDeveloper

+0

puoi scrivere codice completo codice completo integrato che testerò – SwiftDeveloper

1

Un altro modo di fare questo è: è possibile impostare una soglia per ottenere gli elementi durante l'invio di richiesta di volta in volta:

Diciamo che stai recuperando 20 elementi prima volta. Potrai salvare l'ultimo ID del record recuperato o il numero per ottenere l'elenco dei prossimi 20 elementi.

let lastFetchedIndex = 20; 

Suppongo che tu abbia già aggiunto questi record nel tuo myArray. MyArray è l'origine dati di tableView. Ora myArray contiene 40 oggetti. Sto andando a fare una lista di indexPaths di file che devono essere inseriti in tableView ora.

var indexPathsArray = [NSIndexPath]() 


for index in lastFetchedIndex..<myArray.count{ 
    let indexPath = NSIndexPath(forRow: index, inSection: 0) 
    indexPathsArray.append(indexPath) 

} 

Qui sto aggiornando il mio TableView. Assicurati che il tuo data source intenda che il tuo myArray sia già stato aggiornato. In modo che possa inserire correttamente le righe.

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

grazie per la risposta amico ma dove posso aggiungere quei codici? – SwiftDeveloper

+0

L'ho spiegato a passi. Dopo aver ottenuto nuovi pezzi, aggiorna il tuo codice con questo codice. Aggiungi il blocco di elementi provenienti dal server all'array che viene utilizzato come origine dati di tableview. Quindi aggiungi il codice sopra indicato nel tuo codice. Sopra il codice può essere inserito in un unico metodo. –

+0

si prega di modificare la risposta e oltre i miei codici originali e modificarli con i codici di paginazione in seguito controllerò e se funziona approverò la tua risposta .. – SwiftDeveloper

1

avevo bisogno di qualcosa di simile a un progetto e la mia soluzione era:

1 - creare un numberOfObjectsInSubArray variabile (valore iniziale 30 o quello che volete)

2 - creare un sottoarray di aggiungere una serie di oggetti dal vostro allineamento privateList ogni volta che mi tocca "spettacolo più"

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

e usarlo su

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

3- Ogni volta che è necessario mostrare più oggetti, fate:

func addMoreObjectsOnTableView() { 

    numberOfObjectsInSubArray += 30 

    if (numberOfObjectsInSubArray < privateList.count) { 

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

    } else { 

     subArray = privateList?.subarrayWithRange(NSMakeRange(0, privateList.count)) 
    } 

    tableView.reloadData() 
} 

Spero che aiuta

2

Aggiungi un'altra sezione al vostro Tableview, lasciare che questa sezione avere solo una riga che sarà una cella contenente un indicatore di attività, per indicare il caricamento.

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

Il modo più efficace e efficiente per farlo è quello di utilizzare scrollviewDelegate a Tableview Basta aggiungere UIScrollViewDelegate nel vostro viewController Nel controller della 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 
} 

Override due metodi da questo delegato

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) 

       } 
      } 


    } 
+0

Buon lavoro ... Un grosso problema risolve la tua logica semplice –

1

qui è un codice di esempio per la visualizzazione raccolta:

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

SWIFT 3,0-4 ...

Se si invia il numero di pagina nella richiesta API allora questo è il modo ideale per implementare l'impaginazione nella vostra app.

1) dichiarare la pagina corrente variabile con valore iniziale 0 e un bool per verificare se ogni lista viene caricata con valore iniziale falso

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

2) Questa è la funzione che ottiene l'esempio elenco:

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

3) Questa è la funzione che incrementa il numero di pagina e chiama la funzione API

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

4) questo è il metodo che verrà chiamato quando i rotoli ScrollView

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

P.S. il ruolo bool isLoadingList è quello di impedire che la vista di scorrimento ottenga più elenchi in un unico trascinamento verso la parte inferiore della vista tabella.