2016-02-12 10 views
18

Mam powodzenie w pracy tableview z kodami parsowania json.Ale może mieć 1000 więcej pozycji, więc potrzebuję stronicowania podczas przewijania dolnej strony. Nie wiem jak mogę to zrobić moje kody poniżej. Dla celów c mają wiele przykładów, ale dla szybkiego nie znalazłem działającego przykładu. Czekam na twoje pomoce. Myślę, że pomoże to zbyt wielu ludziom. Dziękuję Ci !Swift tableView Paginacja

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

Czy ściągam tysięcy obiektów na raz? –

+0

@ShehzadAli no ale trzeba odświeżyć nowe, gdy przewijanie na dole będzie dobre. Również wiele przedmiotów zajmie dużo czasu. – SwiftDeveloper

Odpowiedz

28

Do tego konieczna jest również zmiana po stronie serwera.

  1. Server zaakceptuje fromIndex i batchSize w url API jako param kwerendy.

    let listUrlString = "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex 
    
  2. W odpowiedzi serwera, nie będzie dodatkowy klucz totalItems. To będzie używane do identyfikacji wszystkich otrzymanych przedmiotów. Tablica lub elementy fromIndex do batchSize liczba elementów.

Po stronie aplikacji

  1. pierwsze loadItem() zostanie wywołana fromIndex = 0 i batchSize = 20 (na przykład viewDidLoad() lub viewWillAppear). removeAll pozycji z privateList tablicy przed wywołaniem loadItem() po raz pierwszy

  2. Server Zwraca tablicę pierwszych 20 elementów i totalItems całkowitą liczbę elementów na serwerze.

  3. Dołącz 20 elementów w privateList tablicy i przeładować tableView

  4. W tableView:cellForRowAtIndexPath metody sprawdzania, czy komórka jest ostatnia komórka. Sprawdź, czy totalItems (serwer formularzy) jest większy niż privateList.count.Oznacza to, że nie ma więcej elementów na serwerze, aby załadować

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

Pytanie:where is refresh ? will be scrolling ?

Odśwież po dołączanie nowych elementów w tablicy, gdy otrzymał odpowiedź serwera. (krok 3)

Przewijanie spowoduje wyzwolenie tableView:cellForRowAtIndexPath dla każdej komórki, gdy użytkownik przewinie. Kod sprawdza, czy jest to ostatnia komórka i pobrać pozostałe elementy. (Krok 4)

Przykładowy projekt dodania:
https://github.com/rishi420/TableViewPaging

+0

gdzie jest odświeżenie? będzie przewijanie? – SwiftDeveloper

+0

Czy możesz napisać pełny kod zintegrowany pełny kod testuję – SwiftDeveloper

+0

możesz napisać pełny kod zintegrowany pełny kod i będę testować – SwiftDeveloper

1

Innym sposobem osiągnięcia tego celu jest: Można ustawić próg dla uzyskania elementów podczas wysyłania żądania za każdym razem:

Powiedzmy, że jesteś pobierania 20 elementów raz pierwszy. Będziesz zapisywać ostatni pobrany identyfikator lub numer, aby uzyskać listę kolejnych 20 elementów.

let lastFetchedIndex = 20; 

Zakładam, że zostały już dodane te zapisy w myArray. MyArray jest źródłem danych tableView. Teraz myArray zawiera 40 obiektów. Zamierzam utworzyć listę indexPaths wierszy, które należy wstawić teraz do tableView.

var indexPathsArray = [NSIndexPath]() 


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

} 

Tutaj aktualizuję mój tableView. Upewnij się, że twój zasób danych oznacza, że ​​twój myArray został już zaktualizowany. Aby mógł poprawnie wstawiać wiersze.

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

dzięki za koleś, ale gdzie mogę dodać te kody? – SwiftDeveloper

+0

Wyjaśniłem to krok po kroku. Po otrzymaniu porcji nowych obiektów zaktualizuj swój kod za pomocą tego kodu. Dodaj porcję elementów pochodzących z serwera do twojej tablicy, która jest używana jako źródło danych tableview. Następnie dodaj powyższy kod w swoim kodzie. Powyższy kod można umieścić w jednej metodzie. –

+0

edytuj odpowiedź i korzystaj z moich oryginalnych kodów i edytuj je przy użyciu kodów paginacji, później sprawdzę i jeśli to zadziała, zatwierdzi Twoją odpowiedź .. – SwiftDeveloper

1

potrzebowałem czegoś podobnego na projekt i moje rozwiązanie było:

1 - utworzyć zmienną numberOfObjectsInSubArray (wartość początkowa 30 lub cokolwiek chcesz)

2 - stworzenie subarray dodać liczbę obiektów ze swojego privateList tablicy za każdym razem i dotknij „pokaż więcej”

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

i używać go na

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

3- Gdy trzeba pokazać więcej obiektów, należy:

func addMoreObjectsOnTableView() { 

    numberOfObjectsInSubArray += 30 

    if (numberOfObjectsInSubArray < privateList.count) { 

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

    } else { 

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

    tableView.reloadData() 
} 

Mam nadzieję, że to pomaga

2

Dodaj kolejny punkt do tableview, niech tę sekcję mieć tylko jeden wiersz, który będzie komórką zawierającą wskaźnik aktywności, w celu oznaczenia obciążenia.

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

Dobry i skuteczny sposób, aby to zrobić jest użycie scrollviewDelegate w tableview Wystarczy dodać UIScrollViewDelegate w viewController Biorąc kontrolera

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

Zastąp dwa sposoby z tym delegat

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

Dobra robota ... Wielki problem rozwiązuję swoją prostą Logikę –

1

tutaj jest przykładowy kod do widoku kolekcji:

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

Jeśli wysyłasz numer strony, na żądanie API to jest to idealny sposób na realizację paginacji w swojej aplikacji.

1) zadeklarować zmienną bieżącej strony z początkowej wartości 0 i bool sprawdzić, czy każdy lista jest ładowany z wartości początkowej fałszywego

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

2) Jest to funkcja, która pobiera Przykładowa lista:

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

3) jest to funkcja, która zwiększa liczbę stron i wywołuje funkcję API

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

4) jest to sposób, który zostanie wywołana, gdy zwoje Scrollview

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

P.S. rola bool isLoadingList polega na tym, aby widok przewijania nie powodował pobierania kolejnych list w jednym przeciągnięciu na dół widoku tabeli.