Swift tableView Pagination Swift tableView Pagination ios ios

Swift tableView Pagination


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


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.


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

//For Paginationvar isDataLoading:Bool=falsevar pageNo:Int=0var limit:Int=20var offset:Int=0 //pageNo*limitvar didEndReached:Bool=falseviewDidLoad(_){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)                }            }    }