Swift tableView Pagination

后端 未结 14 1245
长情又很酷
长情又很酷 2020-11-28 20:00

I have success working tableview with json parsing codes.But may have 1000 more item so need pagination when scrolling bottom side. I dont know how can i do this my codes un

相关标签:
14条回答
  • 2020-11-28 20:34

    Swift 5 (Full comprehensive pagination solution)

    The UI code: https://github.com/eonist/PaginationTable

    The Data Model code: https://github.com/eonist/PaginationService

    Core components:

    • rowData: This array will grow on each scroll-ended-event until it has loaded all items from backend-API
    • paginationAmount: The amount to fetch on each pagination cycle
    • paginationIndex: The current amount of cells (this grows as you load more data
    • isFetching: A boolean that lets the code know if data is already loading or not, to avoid double fetching etc fetchData: Simulates getting data from remote-api Gotchas:

    The example code is not reliant on a backend. It simply tests with data from a file and simulates network calls by sleeping for some seconds The example uses some dependencies in order to speed up the creation of this example. But its basic stuff like AFNetwork, Json parsing, Autollayout. All of which could easily be substituted Requirements:

    Backend-API that can provide the count of items Backend-API that can return items for a range (startIndex, endIndex)

    0 讨论(0)
  • 2020-11-28 20:36

    For that you need to have server side change also.

    1. Server will accept fromIndex and batchSize in the API url as query param.

      let listUrlString =  "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex
      
    2. In the server response, there will be an extra key totalItems. This will be used to identify all items are received or not. An array or items fromIndex to batchSize number of items.

    In the app side

    1. First loadItem() will be called with fromIndex = 0 and batchSize = 20 (for example in viewDidLoad() or viewWillAppear). removeAll items from privateList array before calling loadItem() for the first time

    2. Server returns an array of first 20 items and totalItems total number of items in the server.

    3. Append the 20 items in privateList array and reload tableView

    4. In tableView:cellForRowAtIndexPath method check if the cell is the last cell. And check if totalItems (form server) is greater than privateList.count. That means there are more items in the server to load

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

    Question: where is refresh ? will be scrolling ?

    Refresh after appending new items in the array when server response received. (step 3)

    Scrolling will trigger tableView:cellForRowAtIndexPath for every cell when user scrolls. Code is checking if it is the last cell and fetch remaining items. (step 4)

    Sample project added:
    https://github.com/rishi420/TableViewPaging

    0 讨论(0)
  • 2020-11-28 20:36

    The good and efficient way to do it is by using scrollviewDelegate in tableview Just add UIScrollViewDelegate in your viewController In view controller

    //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 two methods from this delegate

    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 讨论(0)
  • 2020-11-28 20:37

    Another way of doing this is: You may set a threshold for getting elements while sending request each time:

    Lets say you you are fetching 20 elements first time. You will be saving last fetched record id or number for getting list of next 20 elements.

    let lastFetchedIndex = 20;
    

    I am assuming that you have already added these records in your myArray. MyArray is the dataSource of tableView. Now myArray is containing 40 objects. I am going to make a list of indexPaths of rows that needs to be inserted in tableView now.

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

    Here I am updating my tableView. Make sure your dataSource i mean your myArray has already been updated. So that it may insert rows properly.

    self.tableView.beginUpdates()
    tableView!.insertRowsAtIndexPaths(indexPathsArray, withRowAnimation: .Fade)
    self.tableView.endUpdates()
    
    0 讨论(0)
  • 2020-11-28 20:38

    SWIFT 3.0 and 4.0

    If you're sending the page number in the API request then this is the ideal way for implementing pagination in your app.

    1. declare the variable current Page with initial Value 0 and a bool to check if any list is being loaded with initial value false
        var currentPage : Int = 0
        var isLoadingList : Bool = false
    
    1. This is the function that gets the list example:
        func getListFromServer(_ pageNumber: Int){
            self.isLoadingList = false
            self.table.reloadData()
        }
    
    1. This is the function that increments page number and calls the API function
       func loadMoreItemsForList(){
           currentPage += 1
           getListFromServer(currentPage)
       }
       
    
    1. this is the method that will be called when the scrollView scrolls
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            if (((scrollView.contentOffset.y + scrollView.frame.size.height) > scrollView.contentSize.height ) && !isLoadingList){
                self.isLoadingList = true
                self.loadMoreItemsForList()
            }
        }
    

    P.S. the bool isLoadingList role is to prevent the scroll view from getting more lists in one drag to the bottom of the table view.

    0 讨论(0)
  • 2020-11-28 20:44

    here is a sample code for collection view :

    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
       }
    }
    
    0 讨论(0)
提交回复
热议问题