2016-02-12 111 views
18

我已經成功使用json解析代碼工作tableview.But可能有1000多個項目,所以當滾動底部時需要分頁。我不知道如何在下面執行我的代碼。對於Objective-C有很多例子,但對於swift我沒有找到工作的例子。我在等你的幫助。我認爲會有太多人幫助。謝謝 !Swift tableView分頁

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

你一次讀取千個對象? –

+0

@ShehzadAli不,但需要刷新新的時候,滾動底部會很好。許多項目也需要很多時間。 – SwiftDeveloper

回答

28

爲此,您還需要更改服務器端。

  1. 服務器將在API網址查詢參數接受fromIndexbatchSize

    let listUrlString = "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex 
    
  2. 在服務器響應,會有一個額外的鍵totalItems。這將用於識別所有物品是否收到。一個數組或項目fromIndexbatchSize數量的項目。

在應用側

  1. 首先loadItem()將與fromIndex = 0batchSize = 20和(例如在viewDidLoad()viewWillAppear)被調用。主叫loadItem()首次

  2. Server返回的第一20項的陣列,並且在服務器中的項目totalItems總數之前的removeAll從privateList數組項。

  3. 追加20個項目中privateList陣列和重新加載tableView

  4. tableView:cellForRowAtIndexPath方法檢查,如果該細胞是最後單元。並檢查totalItems(表單服務器)是否大於privateList.count。這意味着有更多的項目在服務器加載

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

問:當收到服務器響應數組中追加新項目後where is refresh ? will be scrolling ?

刷新。 (步驟3)

當用戶滾動時,滾動將爲每個單元觸發tableView:cellForRowAtIndexPath。代碼正在檢查它是否是最後一個單元格並提取剩餘的項目。 (步驟4)

示例項目補充說:
https://github.com/rishi420/TableViewPaging

+0

刷新哪裏?將滾動? – SwiftDeveloper

+0

你能寫出完整的代碼集成完整的代碼我會測試 – SwiftDeveloper

+0

你能寫出完整的代碼集成完整的代碼我會測試 – SwiftDeveloper

1

這樣做的另一種方法是:你可以設置一個門檻,讓元素,同時每次發送請求:

比方說你,你是取20元的第一次。您將保存上次獲取的記錄ID或編號,以獲取下20個元素的列表。

let lastFetchedIndex = 20; 

我假設你已經在myArray中添加了這些記錄。 MyArray是tableView的數據源。現在myArray包含40個對象。現在我將列出需要在tableView中插入的行的indexPaths。

var indexPathsArray = [NSIndexPath]() 


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

} 

這裏我正在更新我的tableView。確保你的dataSource我的意思是你的myArray已經被更新了。以便它可以正確插入行。

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

謝謝你的回答,但我可以在哪裏添加代碼? – SwiftDeveloper

+0

我已經在步驟中解釋它。獲取大量新對象後,用此代碼更新您的代碼。將來自服務器的項目塊添加到您正在用作tableview數據源的數組中。然後在代碼中添加上面提到的代碼。上面的代碼可以放在一個方法中。 –

+0

請編輯您的答案,並通過我的原始代碼,並與您的分頁代碼後編輯我會檢查,如果它的作品,我會批准你的答案.. – SwiftDeveloper

1

我需要一個項目類似的東西,我的解決辦法是:

1 - 創建一個變量numberOfObjectsInSubArray(初始值30或任何你想要的)

2 - 創建一個子陣從privateList陣列每一次添加多個對象的我點擊「顯示更多」

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

,並將其用於

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

3-每當你需要表現出更多的對象,這樣做:

func addMoreObjectsOnTableView() { 

    numberOfObjectsInSubArray += 30 

    if (numberOfObjectsInSubArray < privateList.count) { 

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

    } else { 

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

    tableView.reloadData() 
} 

我希望它能幫助

2

添加其他欄目到你的tableview,讓這部分只有1行將是一個包含活動指標的單元格,用於表示加載。

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

良好和有效的方式做到這一點是通過實現代碼如下 使用scrollviewDelegate只是在你viewController 添加UIScrollViewDelegate在視圖控制器

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

改寫從該委託兩種方法

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

幹得好...大問題解決你的簡單邏輯 –

1

這裏是收集視圖的示例代碼:

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

如果你發送API請求的頁面數,那麼這是對你的應用程序實現分頁的理想方式。

1)聲明使用初始值0和布爾變量當前頁,以檢查是否正在加載有初始值假

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

2)這是一個獲取列表示例功能的任何列表:

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

3)這是一個增加頁碼和調用API函數的函數

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

4),這是該方法將被調用時,滾動視圖滾動

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

P.S. bool isLoadingList的作用是阻止滾動視圖從一個拖動中獲取更多列表到表格視圖的底部。