2016-02-12 2 views
18

Ich habe Erfolg Arbeit Tabellenansicht mit JSON Parsing-Codes.Aber kann 1000 weitere Artikel haben so Paginierung beim Scrollen Unterseite. Ich weiß nicht, wie ich das meine Codes unten tun kann. Für objective-c habe ich eine Menge Beispiele, aber für swift habe ich kein funktionierendes Beispiel gefunden. Ich warte auf deine Hilfe. Ich denke, es wird zu vielen Menschen helfen. Vielen Dank !Swift tableView Paginierung

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

Sind Sie tausend Objekte zu einem Zeitpunkt, zu holen? –

+0

@ShehzadAli nein, aber müssen neue aktualisieren, wenn der untere Bildlauf gut sein wird. Auch viele Gegenstände brauchen viel Zeit. – SwiftDeveloper

Antwort

28

Dafür müssen Sie auch Server Seite ändern müssen.

  1. Server wird fromIndex und batchSize in der API URL als Abfrage param akzeptieren.

    let listUrlString = "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex 
    
  2. In der Server-Antwort wird es einen zusätzlichen Schlüssel totalItems sein. Dies wird verwendet, um alle Artikel zu identifizieren, die empfangen werden oder nicht. Ein Array oder Elemente fromIndex bis batchSize Anzahl der Elemente.

im APP Seiten

  1. Erste loadItem() mit fromIndex = 0 und batchSize = 20 (für in viewDidLoad() oder viewWillAppear Beispiel) bezeichnet werden.

  2. Server gibt eine Reihe von ersten 20 Elemente und totalItems Gesamtzahl der Elemente im Server RemoveAll Elemente aus privateList Array vor loadItem() zum ersten Mal aufgerufen wird.

  3. Append die 20 Elemente in privateList Array und tableView

  4. In tableView:cellForRowAtIndexPath Verfahren Prüfung neu geladen, wenn die Zelle die letzte Zelle ist. Überprüfen Sie, ob totalItems (Formularserver) größer als privateList.count ist.Das bedeutet, dass es mehr Elemente im Server sind

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

Frage zu laden:where is refresh ? will be scrolling ?

Refresh nach neuen Elemente im Array anhängt, wenn die Serverantwort empfangen. (Schritt 3)

Scrollen löst tableView:cellForRowAtIndexPath für jede Zelle aus, wenn Benutzer scrollt. Der Code prüft, ob es sich um die letzte Zelle handelt, und holt die verbleibenden Elemente. (Schritt 4)

Beispielprojekt hinzugefügt:
https://github.com/rishi420/TableViewPaging

+0

wo ist aktualisieren? wird gescrollt? – SwiftDeveloper

+0

können Sie schreiben vollständigen Code integrierten vollständigen Code ich werde testen – SwiftDeveloper

+0

können Sie schreiben vollständigen Code integrierten vollständigen Code ich werde testen – SwiftDeveloper

1

Ein anderer Weg, dies zu tun ist: Sie einen Schwellenwert festlegen können Elemente für immer während Anfrage jedes Mal zu senden:

Hier können Sie sagen, Sie zum ersten Mal 20 Elemente abgerufen werden. Sie werden die zuletzt abgerufene Datensatz-ID oder Nummer speichern, um eine Liste der nächsten 20 Elemente zu erhalten.

let lastFetchedIndex = 20; 

Ich gehe davon aus, dass Sie diese Datensätze bereits in Ihrem myArray hinzugefügt haben. MyArray ist die DataSource von TableView. Jetzt enthält myArray 40 Objekte. Ich werde eine Liste von indexPaths von Zeilen erstellen, die jetzt in tableView eingefügt werden müssen.

var indexPathsArray = [NSIndexPath]() 


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

} 

Hier aktualisiere ich meine TableView. Stellen Sie sicher, dass Ihre Datenquelle bedeutet, dass Ihr myArray bereits aktualisiert wurde. Damit es Zeilen richtig einfügen kann.

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

danke für antwort dude aber wo kann ich diese codes hinzufügen? – SwiftDeveloper

+0

Ich habe es in Schritten erklärt. Nachdem Sie einen Teil der neuen Objekte erhalten haben, aktualisieren Sie Ihren Code mit diesem Code. Fügen Sie den Teil des Servers, der vom Server kommt, zu Ihrem Array hinzu, der als Datenquelle der Tabellenansicht verwendet wird. Fügen Sie dann den oben genannten Code in Ihrem Code hinzu. Der obige Code kann in einer Methode platziert werden. –

+0

Bitte bearbeiten Sie Ihre Antwort und hinter meine ursprünglichen Codes und bearbeiten Sie sie mit Ihrem Paginierung Codes später werde ich überprüfen, und wenn es funktioniert, werde ich Ihre Antwort genehmigen .. – SwiftDeveloper

1

Ich brauchte etwas ähnliches an einem Projekt und meine Lösung war:

1 - erstellen Sie eine Variable numberOfObjectsInSubArray (Anfangswert 30 oder was auch immer Sie wollen)

2 - erstellen Sie eine Sub-Array eine Reihe von Objekten aus Ihrem privateList Array i tippen jedes Mal hinzuzufügen, „mehr“

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

Und es auf

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

3- verwenden Jedes Mal, wenn Sie mehrere Objekte zeigen müssen, tun:

func addMoreObjectsOnTableView() { 

    numberOfObjectsInSubArray += 30 

    if (numberOfObjectsInSubArray < privateList.count) { 

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

    } else { 

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

    tableView.reloadData() 
} 

Ich hoffe, es

2

weiteren hinzufügen Abschnitt zu Ihrem Tableview hilft, lassen Sie diesen Abschnitt habe nur 1 Zeile, die eine Zelle sein wird, die einen Aktivitätsindikator enthält, um das Laden zu bezeichnen.

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

Die gute und effiziente Art und Weise, es zu tun ist durch scrollviewDelegate in Tableview mit Nur UIScrollViewDelegate in Ihrem viewController In Controller-Ansicht

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

Aufschalten zwei Methoden von diesem Delegaten

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

Gute Arbeit ... Großes Problem lösen Sie Ihre einfache Logik –

1

Hier ist ein Beispielcode für die Sammlungsansicht:

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

Wenn Sie die Seitenzahl in der API-Anfrage sind zu senden, dann ist dies der ideale Weg, Paginierung in Ihrer Anwendung für die Umsetzung.

1) erklären die variable Strom Seite mit dem Anfangswert 0 und einem Bool zu überprüfen, ob jede Liste mit Anfangswert geladen wird falsch

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

2) Dies ist die Funktion, das die Liste Beispiel bekommt:

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

3) Dies ist die Funktion, die Seitennummer inkrementiert und ruft die API-Funktion

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

4) Dies ist die Methode, die, wenn die Scroll scrollt

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

P.S. genannt wird Die bool isLoadingList-Rolle soll verhindern, dass die Bildlaufansicht mehr Listen in einem Ziehvorgang an den unteren Rand der Tabellenansicht bringt.