How to implement infinite scrolling (page nate) in Swift TableView

How to implement infinite scrolling (page nate) in Swift TableView

In my usual implementation, I somehow implemented infinite scrolling (page nate) of TableView, so I would like to write it here again as a memorandum.

What is pagination in the first place?

Pagination is an English word that means pagination. When posting a large amount of content or links on a web page, etc., the display may not be completely divided on one page or the processing may take time. Therefore, we may divide pages with similar design into multiple pages and arrange links to each page at the bottom of the page. This kind of page structure and the processing and functions that automatically divide pages by software are called pagination.

Even in Youtube search, the search results are displayed and there is "1,2,3,4,5" under it, and you can see the lower search results on each page, right? (The latest order is older, In order of relevance, the relevance is getting older ...) Its configuration and function is called pagination.

What is infinite scrolling?

A technique in which the user keeps scrolling through a large amount of content.

You can see the contents of the lower layers more and more by scrolling on Instagram etc., right?

This is achieved by acquiring and displaying new information (such as Model) each time you scroll down. As an image, if you present a large amount of information at once with Pagenate, it will take time for all processing, so display a certain number at a time and add the information for the second page if you go to the end, and also If you go to the end, the information for the third page will be added ...

Implementation method in TableView

STEP1: Until TableView is displayed

I will omit it

STEP2: Prepare API to get information to be displayed (create or divert)

I will omit the details.

I get it from my own API, so I will describe it according to the method. This time, if you send the number of pages, you can get the data for that amount.

Please read the information acquisition part as the API or method you use.

STEP3: Prepare variables

Let's prepare variables to be used for infinite scrolling. ・ Array to store data to be displayed ・ Current number of displayed pages ・ Current display status

ViewControlle.swift



import UIKit
import Alamofire
import SwiftyJSON

class testViewControlle:UIViewController,UITableViewDelegate,UITableViewDataSource{

      //==========Variables to prepare From here============
      //Array of data to display
      var datas:[Data] = []
      //Page Nation related variables
      var pageCount:Int = 1
      //Display status
      var displayStatus:String = "standby"
      //Total number of pages
      var total_pages:Int = 1
      //==========Variables to prepare up to here============

      override func viewDidLoad() {
          super.viewDidLoad()
          
          tableView.dataSource = self
          tableView.delegate = self

          getDatas()
      }

       func numberOfSections(in tableView: UITableView) -> Int {
             // #warning Incomplete implementation, return the number of sections
             return 1
        }

       func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
             // #warning Incomplete implementation, return the number of rows
             return datas.count
        }

       func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
              //Build cells as you like
              let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
              return cell
        }

        //Method to get data
        func getDatas(){
            
            //Described here the process of acquiring the information of the corresponding page using API
            //Example
             let getUelText = "https://test.com/testdata_get/" + String(pageCount)
             let getUrl = getUelText.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
             AF.request(getUrl,method: .get,parameters: nil,encoding: JSONEncoding.default).responseJSON{(responce) in

                switch responce.result{
                     case .success:
                         let mJson:JSON = JSON(responce.data as Any)
                         var dateCount:Int = mJson["count"].int!
                         var mData:Data = Data()    
                         //Example)Set the acquired information in mData here
                         self.datas.append(mData) 
                         self.tableView.reloadData()

                     case .failure(let error):
                     
                     
                 }
             }


        }

}

STEP4: Detect the scroll position and get the data when the end is approaching.

-Use the "scrollViewDidScroll" method to detect the scroll position. -Get the current scroll position and the bottom without the method, and go to get the last approached data. ・ When you go to get the information, increase PageCount by 1 so that you can get the information of the next page.

ViewControlle.swift



import UIKit
import Alamofire
import SwiftyJSON

class testViewControlle:UIViewController,UITableViewDelegate,UITableViewDataSource{

      //Array of data to display
      var datas:[Data] = []
      //Page Nation related variables
      var pageCount:Int = 1
      //Display status
      var displayStatus:String = "standby"
      //Total number of pages
      var total_pages:Int = 1

      override func viewDidLoad() {
          super.viewDidLoad()
          
          tableView.dataSource = self
          tableView.delegate = self

          getDatas()
      }

       func numberOfSections(in tableView: UITableView) -> Int {
             // #warning Incomplete implementation, return the number of sections
             return 1
        }

       func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
             // #warning Incomplete implementation, return the number of rows
             return datas.count
        }

       func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
              //Build cells as you like
              let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
              return cell
        }

        //Method to get data
        func getDatas(){
            
            //Described here the process of acquiring the information of the corresponding page using API
            //Example
             let getUelText = "https://test.com/testdata_get/" + String(pageCount)
             let getUrl = getUelText.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
             AF.request(getUrl,method: .get,parameters: nil,encoding: JSONEncoding.default).responseJSON{(responce) in

                switch responce.result{
                     case .success:
                         let mJson:JSON = JSON(responce.data as Any)
                         var dateCount:Int = mJson["count"].int!
                         var mData:Data = Data()    
                         //Example)Set the acquired information in mData here
                         self.datas.append(mData) 
                         self.tableView.reloadData()

                     case .failure(let error):
                     
                     
                 }
             }


        }

           //==========STEP4 scrollViewDidScroll From here============
           func scrollViewDidScroll(_ scrollView: UIScrollView) {
               let currentOffsetY = scrollView.contentOffset.y
               let maximumOffset = scrollView.contentSize.height - scrollView.frame.height
               let distanceToBottom = maximumOffset - currentOffsetY
               if(distanceToBottom) {
                  pageCount += 1
                  getDatas()
               }
            }
           //==========So far============

}

STEP5: Arrange the conditions and make the content "trying to get duplicates" and "trying to get additional data even though there is no more data"

-In the current "scrollViewDidScroll", if the distance to the bottom is 500 or less, getDatas will be performed many times. → Use the displayStatus variable to make adjustments so that you do not try to get duplicates. -In the current "scrollViewDidScroll", getDatas will be performed even if there is no data that can be acquired anymore. → Use the total_pages variable to make adjustments so that you do not try to get duplicates.

ViewControlle.swift



import UIKit
import Alamofire
import SwiftyJSON

class testViewControlle:UIViewController,UITableViewDelegate,UITableViewDataSource{

      //Array of data to display
      var datas:[Data] = []
      //Page Nation related variables
      var pageCount:Int = 1
      //Display status
      var displayStatus:String = "standby"
      //Total number of pages
      var total_pages:Int = 1

      override func viewDidLoad() {
          super.viewDidLoad()
          
          tableView.dataSource = self
          tableView.delegate = self

          getDatas()
      }

       func numberOfSections(in tableView: UITableView) -> Int {
             // #warning Incomplete implementation, return the number of sections
             return 1
        }

       func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
             // #warning Incomplete implementation, return the number of rows
             return datas.count
        }

       func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
              //Build cells as you like
              let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
              return cell
        }

        //Method to get data
        func getDatas(){
             //==========STEP5 from here============
             self.displayStatus = "loading"
             //==========So far============
            
            //Described here the process of acquiring the information of the corresponding page using API
            //Example
             let getUelText = "https://test.com/testdata_get/" + String(pageCount)
             let getUrl = getUelText.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
             AF.request(getUrl,method: .get,parameters: nil,encoding: JSONEncoding.default).responseJSON{(responce) in
                //==========STEP5 from here============
                 self.displayStatus = "standby"
                //==========So far============

                switch responce.result{
                     case .success:
                         let mJson:JSON = JSON(responce.data as Any)
                         var dateCount:Int = mJson["count"].int!
                         total_pages = //Get if you can get the total number of pages
                         var mData:Data = Data()    
                         //Example)Set the acquired information in mData here
                         self.datas.append(mData) 
                         self.tableView.reloadData()

                     case .failure(let error):
                         print(error)
                     
                 }
             }


        }


           func scrollViewDidScroll(_ scrollView: UIScrollView) {
               let currentOffsetY = scrollView.contentOffset.y
               let maximumOffset = scrollView.contentSize.height - scrollView.frame.height
               let distanceToBottom = maximumOffset - currentOffsetY
               //==========STEP5 from here============
                if(distanceToBottom < 500 && displayStatus == "standby" && total_pages != pageCount){
                    pageCount += 1
                    getDatas()
                }
               //==========So far============
               
            }


}

Complete!!

Summary

-Prepare variables. -Get the scroll position with "scrollViewDidScroll". ・ When the scroll approaches the bottom, go to get the next data. -Let's control under various conditions so that the data (page) will not be duplicated while you are going to get it, or you will not go to get it when there is no more data (page).

Recommended Posts

How to implement infinite scrolling (page nate) in Swift TableView
How to implement UICollectionView in Swift with code only
[swift5] How to specify color in hexadecimal
How to implement search functionality in Rails
How to implement date calculation in Java
How to implement Kalman filter in Java
[Swift] How to fix Label in UIPickerView
[Swift] How to implement the countdown function
How to implement coding conventions in Java
[Swift5] How to implement standby screen using'PKHUD'
How to implement ranking functionality in Rails
[Swift5] How to implement animation using "lottie-ios"
How to implement asynchronous processing in Outsystems
How to overwrite Firebase data in Swift
How to implement more than one top page in Rails breadcrumb trail
How to display a web page in Java
[Swift] How to implement the LINE login function
Note how to use Swift super basic TableView
[swift5] How to implement the Twitter share function
How to add sound in the app (swift)
How to implement a like feature in Rails
[Swift] How to implement the fade-in / out function
How to implement optimistic locking in REST API
How to execute tasks in parallel in Swift in Swift Package
How to implement Pagination in GraphQL (for ruby)
How to implement guest login in 5 minutes in rails portfolio
How to implement a like feature in Ajax in Rails
Summary of how to implement default arguments in Java
[Swift] How to use UserDefaults
How to use Swift UIScrollView
Implement Swift UITextField in code
[Swift5] How to avoid applying dark mode (dark appearance) in code
How to implement one-line display of TextView in Android development
[Rails] How to implement scraping
Implement writing and reading to Property List (.plist) in Swift
[Java] How to implement multithreading
How to change BackgroundColor etc. of NavigationBar in Swift UI
How to implement a job that uses Java API in JobScheduler
[Swift] How to implement the Twitter login function using Firebase UI ①
[Behavior confirmed in December 2020] How to implement the alert display function
[RubyOnRails] How to implement pull-down in form_with based on table data
How to implement UI automated test using image comparison in Selenium
[Swift] How to implement the Twitter login function using Firebase UI ②
How to find May'n in XPath
How to hide scrollbars in WebView
How to run JUnit in Eclipse
Try to implement Yubaba in Ruby
[Rails] How to write in Japanese
How to run Ant in Gradle
How to learn JAVA in 7 days
How to get parameters in Spark
How to install Bootstrap in Ruby
[Swift] How to use SwiftLint (cocoapods)
[Swift] How to use Unwind segue
How to use InjectorHolder in OpenAM
[Swift] How to send a notification
How to introduce jQuery in Rails 6
[Rails] How to implement star rating
How to use classes in Java?
How to name variables in Java
How to set Lombok in Eclipse