Search code examples
swiftxcodetableview

Half of the list will be loaded at the beginning, and when it comes to the end of this list, the other half will be added below inside table view


I have a tableView and json data.I want tableview load half in json data. When table view scroll comes to the end of the first half , the other half will be load.Can anyone know how I can ?


Solution

  • I believe you will have to do some pagination type of processing on your side with the help of scrollViewDidScroll to observe when you reach the end of a the tableview to load the next batch

    Start by setting some initial variables to help you track the paging process.

    var pageStart = 0
    var pageSize = 15
    
    // scrollViewDidScroll will be called several times
    // so we need to be able to block the loading process
    var isLoadingItems = false
    
    // Array of 50 values which you get from the API
    // For example your JSON data
    var totalNumberOfItems = (0...49).reduce([Int]())
    { (result, number) in
        
        var array = result
        array.append(number)
        return array
    }
    
    // This will periodically be filled with items from totalNumberOfItems
    var itemsToLoad: [Int] = []
    

    I create this loading function which helps with adding the items in batches and reloading the tableview appropriately

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)
        loadItems()
    }
    
    private func loadItems(withDelay delay: Double = 0) {
        
        // Check that there are items to load
        if pageStart < totalNumberOfItems.count, !isLoadingItems {
            
            isLoadingItems = true
            
            // The delay and dispatch queue is just to show you the
            // loading of data in batches, it is not needed for the
            // solution
            if delay > 0 {
                presentLoader()
            }
            
            DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                
                if delay > 0 {
                    
                    // dismiss the loader
                    self.dismiss(animated: true, completion: nil)
                }
                
                // Calculate the page end based on the page size or on
                // the number of items remaining to load if the page size
                // is greater than the number of items remaining
                var pageEnd = self.pageStart + self.pageSize - 1
                
                if pageEnd > self.totalNumberOfItems.count {
                    let remainingItems = self.totalNumberOfItems.count - self.pageStart - 1
                    pageEnd = self.pageStart + remainingItems
                }
                
                let newItems = Array(self.totalNumberOfItems[self.pageStart ... pageEnd])
                self.itemsToLoad.append(contentsOf: newItems)
                self.pageStart = pageEnd + 1
                
                let indexPaths = newItems.map { IndexPath(row: $0,
                                                          section: 0) }
                
                // Update the table view
                self.tableView.beginUpdates()
                self.tableView.insertRows(at: indexPaths, with: .fade)
                self.tableView.endUpdates()
                
                // scroll to first newly inserted row
                if let firstNewRow = indexPaths.first {
                    self.tableView.scrollToRow(at: firstNewRow,
                                               at: .top,
                                               animated: true)
                }
                
                
                // Unlock the loading process
                self.isLoadingItems = false
            }
        }
    }
    

    Then observe if you reached the end using scrollViewDidScroll and reload the tableview to show the inserted rows

    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
        
        // Check that the current scroll offset is > 0 so you don't get
        // any false positives when the table view is set up
        // and check if the current offset has reached the end
        if scrollView.contentOffset.y >= 0 &&
            scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height) {
            
            print("reached end, load more")
            
            // Load more data
            loadItems(withDelay: 1)
        }
    }
    

    Here is how that will look:

    UITableView paging reload end of table view scrollview swift iOS

    If you found some part difficult to follow or add into your own code, the complete code which can run as is can be found here: