with this json it seems that I cannot do a simple append array because pagination only works with the number of pages. How can i add infinite scrolling / pagination with pages? Now page 1 is loaded with 20 items, it works, but how can I load the other pages and keep the previously loaded ones too?
Right now my VC looks like this:
import UIKit
struct SwiftData: Codable {
let results: [Results]
}
struct Results: Codable {
let title: String?
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var popularMoviesArray = [Results]()
var tableViewCell = TableViewCell()
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
swiftManager.fetchUrl()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return popularMoviesArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: ConstantFile.cellIdentifier, for: indexPath) as! TableViewCell
var item: Results
item = popularMoviesArray[indexPath.row]
cell.labelTitle.text = item.title
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: ConstantFile.performSegueIdentifier, sender: indexPath.row)
tableView.deselectRow(at: indexPath, animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier != nil else {
return
}
let letRow = sender as? Int
switch segue.identifier {
case "goToDetail":
(segue.destination as! ViewControllerDetail).itemDetail = popularMoviesArray[letRow!]
default:
return
}
}
}
struct SwiftManager {
let baseURL = "https://api.themoviedb.org/3/movie/popular"
let apiKey = “xxxxxxxxxxxxxx”
let filterURL1 = "language=en-US"
let filterURL2 = "sort_by=popularity.desc"
let filterURL3 = "page=1"
func fetchUrl() {
let urlString = "\(baseURL)?api_key=\(apiKey)&\(filterURL1)&\(filterURL2)&\(filterURL3)"
performRequest(with: urlString)
}
func performRequest(with urlString: String) {
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
self.delegate?.didFailWithError(error: error!)
return
}
if let safeData = data {
if let movies = self.parseJSON(safeData) {
self.delegate?.didUpdateStruct(self, swiftData: movies)
}
}
}
task.resume()
}
}
func parseJSON(_ swiftData: Data) -> SwiftData? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(SwiftData.self, from: swiftData)
return decodedData
} catch {
print(error)
return nil
}
}
}
You can see that you have reached the bottom of the list with willDisplay
function from the UITableViewDelegate
protocol. like below code:
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forItemAt indexPath: IndexPath) {
let lastIndex = self.popularMoviesArray.count - 1
if indexPath.row == lastIndex {
// api call and get next page
}
}
and you can call API to get the next page data. then append new data to your data source list and reload tableView:
self.popularMoviesArray.append(contentsOf: newListData)
self.tableView.reloadData()