Swift tableView Pagination

后端 未结 14 1246
长情又很酷
长情又很酷 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:45

    I've tried an approach with willDisplayCell. But it produces unwanted stops during scrolling which makes the user experience not good. I think a better way is to do it in scrollViewDidEndDecelerating delegate method. It calls when the scroll finishes and only then new data comes. User sees that there is new content and scroll again if he wants. I've taken the answer here but instead of scrollViewDidEndDragging I use scrollViewDidEndDecelerating. It looks just better in my case. Here is some code from my project.

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        guard scrollView == tableView,
            (scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height,
            !viewModel.isLastPeriodicsPage else { return }
    
        viewModel.paginatePeriodics(tableView.getLastIndexPath())
    }
    
    0 讨论(0)
  • 2020-11-28 20:47

    Add another section to your tableview, let this section have only 1 row which will be a cell containing an activity indicator, to denote loading.

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

    Made a General purpouse pagination framework:

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

    I needed something similar on a project and my solution was:

    1 - create a variable numberOfObjectsInSubArray (initial value 30 or whatever you want)

    2 - create a subarray to add a number of objects from your privateList array every time i tap "show more"

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

    And use it on

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

    3- Whenever you need to show more objects, do:

    func addMoreObjectsOnTableView () {
    
        numberOfObjectsInSubArray += 30
    
        if (numberOfObjectsInSubArray < privateList.count) {
    
            subArray = privateList?.subarrayWithRange(NSMakeRange(0, numberOfObjectsInSubArray))  
    
        } else {
    
            subArray = privateList?.subarrayWithRange(NSMakeRange(0, privateList.count))  
        }
    
        tableView.reloadData()
    }
    

    I hope it helps

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

    API handler is api handler for network call that just do POST and GET calls. getNotifications is basically just a post call with params( offset and pageSize ) and in response there is list. Main logic is changing offset depending on cell in willDisplay collectionView delegate. Comment if you having any question , happy to help.

    var isFetching: Bool = false
    var offset = 0
    var totalListOnServerCount = 20 // it must be returned from server
    var pageSize = 10 // get 10 objects for instance
    // MARK: - API Handler
    private func fetchNotifications(){
        // return from function if already fetching list
        guard !isFetching else {return}
            if offset == 0{
                // empty list for first call i.e offset = 0
                self.anyList.removeAll()
                self.collectionView.reloadData()
            }
            isFetching = true
            // API call to fetch notifications with given offset or page number depends on server logic just simple POST Call
            APIHandler.shared.getNotifications(offset: offset) {[weak self] (response, error) in
                if let response = response {
                    self?.isFetching = false
                    if self?.offset == 0{
                        // fetch response from server for first fetch
                        self?.notificationsResponse = response
                        if self?.refreshControl.isRefreshing ?? false {
                            self?.refreshControl.endRefreshing()
                        }
                    }else{
                        // append if already exist ( pagination )
                        self?.notificationsResponse?.notifications.append(contentsOf: response.notifications)
                    }
                    self?.collectionView.reloadData()
    
                }
    
            }
    }
    
    
    // MARK: - Collection View Delegate
    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    
        guard let anyList = responseFromServer else { return }
        // check if scroll reach last index available and keep fetching till our model list has all entries from server
        if indexPath.item == anyList.count - 1 && anyList.count  < totalListOnServerCount{
    
            offset += pageSize
            fetchNotifications()
    
        }
    }
    
    0 讨论(0)
  • 2020-11-28 20:52

    By using UITableViewDelegate, u can call the function

       func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        let lastItem = self.mes.count - 1
        if indexPath.row == lastItem {
            print("IndexRow\(indexPath.row)")
            if currentPage < totalPage {
                currentPage += 1
               //Get data from Server
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题