arraysswiftuitableviewcustom-scrolling

How to make a loop appending 20 -20 rows in a tableview when scrolling?


I have a tableview, where I get sometimes 1000 or 40 or sometime even 4 values, but I want that when I got more than 100 values I want to display my array in a 10 - 10 scrolling.

Scrolling the tableview up, I need a scrolling pause after 10 rows are scrolled up, with this code it is giving errors, My array is in [Any] and want to scrolling like Facebook and instagram

I want to get my array into 10 rows first and then I can append the next 10.

    var allUserArray = [Any]()
    override func viewDidLoad() {
        super.viewDidLoad()

    var index = allUserArray.first 
    while index < limit {
    allUserArray.append(index)
    index = index + "1"
  }

  }

  extension AdvanceSearchViewController: UITableViewDataSource,           UITableViewDelegate {

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return allUserArray.count 

}

   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "advanceSearch") as! AdvanceSearchTableViewCell


    let userData = allUserArray[indexPath.row] as! [String: Any]

    let dob = userData["dob"] as! String
    let age = self.getAgeFromDate(dob: dob)
    let photo1 = userData["photo1"] as? String
    let height = userData["Height"] as? String ?? "null"
    let religion = userData["Religion"] as? String ?? "null"


    cell.userNameLabel.text = "HM- \(userData["ProfileID"] as!   String)"
    cell.userProfessionLabel.text = userData["Profession"] as? String ?? "null"
    cell.userAgeLabel.text = "\(age), \(height), \(religion)"

    if let profileImage = photo1 {
        urlStringOne = "\(USER_IMAGE_BASE_URL)\(profileImage)"
    } else {
        if (UserDefaults.standard.value(forKey: "gender") as! String    == "Female") {
            urlStringOne = "\(USER_IMAGE_URL_MALE)"
        } else {
            urlStringOne = "\(USER_IMAGE_URL_FEMALE)"
        }
    }

   loadImage(urlStringOne, cell)

    return cell
}


   func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if self.allUserArray.count != nil {

        self.totalEnteries = self.allUserArray.count
        print("idealist/\(self.allUserArray.count)")
        print("total123/\(self.totalEnteries)")

        var entries = allUserArray.count - 1
          print("total-00/\(entries)")

      If indexPath.row == entries {
        print("(----------)")
        if allUserArray.count < totalEnteries {

            var index = allUserArray.count as! String
            self.limit = index + "20"
            while index < self.limit {
                self.allUserArray.append(index)
                index = index + "1"
                }
            self.perform(#selector(self.loadTable), with: nil, afterDelay: 2.0)
          }
        }

}

}
   @objc func loadTable() {
    self.advanceSearchTableView.reloadData()
   }

}

Solution

  • I'll elaborate the pagination in tableView using an example. You can go through it and then implement it in your project.

    1. Let's assume you've a String array that contains around 500 elements.

    var allUsers = [String](repeating: "User", count: 500)
    

    2. Create another String array that initially contains first 10 elements from allUsers array.

    var dataSource = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.addElements() //explained next..
    }
    

    The dataSource array will act as the actual dataSource for the tableView.

    3. Let's maintain an offset that'll keep track of the index from which we need to add next 10 elements, i.e.

    var nextOffset = 0
    
    func addElements() {
        let newOffset = nextOffset+10
        for i in nextOffset..<newOffset {
            dataSource.append(allUsers[i])
        }
        nextOffset = newOffset
    }
    

    addElements() method simply add next 10 elements starting from the nextOffset.

    4. The UITableViewDataSource methods look like,

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = "\(dataSource[indexPath.row]) : \(indexPath.row)"
        return cell
    }
    

    5. Now implement UITableViewDelegate method - tableView(_:willDisplay:forRowAt:)

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        let currentCount = self.dataSource.count
        if currentCount < 500 && indexPath.row == (currentCount-1) { //last row
            self.addData()
            self.setUpLoaderView(toShow: true)
        } else {
            self.setUpLoaderView(toShow: false)
        }
    }
    

    In the above methods, I've checked if the cell is being displayed for the last row. If yes, then we add more data to it using addData() method and show a loaderView at bottom using setUpLoaderView(toShow:) method.

    6. Here is the definition of both the methods,

    func addData() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
            self.addElements()
            self.tableView.reloadData()
        }
    }
    
    func setUpLoaderView(toShow: Bool) {
        if toShow {
            self.tableView.tableFooterView?.isHidden = false
            self.tableView.tableFooterView = self.loaderMoreView
        } else {
            self.tableView.tableFooterView = UIView()
        }
    }
    

    In addData() I've added a delay of 10 seconds as per your requirement. So the loader will be visible for 10 seconds before the tableView is updated with new data.

    7. loaderMoreView is simply a UIActivityIndicatorView that is set as the tableFooterView, like:

    private lazy var loaderMoreView: UIView = {
        let loaderView = UIActivityIndicatorView(style: .whiteLarge)
        loaderView.color = UIColor.gray
        loaderView.startAnimating()
        return loaderView
    }()