Reputation: 23
I have some problem with pagination with JSON data. I can show only one page, but I need to show the next page when it last cell.
I've tried this way with willDisplay, but it didn't work. I think I need to keep my data in some array, however I don't know how to do it. Also I have model for data from JSON. Please help me, pagination drives me crazy :(
Please, don't pay attention to func getDate in viewDidLoad, it's another problem :D
import UIKit
class FilmsViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var searchController: UISearchController!
var films = Films()
var page = 1
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
tableView.tableHeaderView = searchController.searchBar
tableView.reloadData()
getDate(title: "World", page: page)
}
private let endPoint = "http://www.omdbapi.com/"
func getDate(title: String, page: Int) {
var urlComponents = URLComponents(string: endPoint)
let querySearchNameOfFilm = URLQueryItem(name: "s", value: title)
let querytypeOfFilms = URLQueryItem(name: "type", value: "movie")
let queryPages = URLQueryItem(name: "page", value: String(page))
let queryApiKey = URLQueryItem(name: "apikey", value: "a6c7f954")
urlComponents?.queryItems = [querySearchNameOfFilm,
querytypeOfFilms,
queryPages,
queryApiKey]
guard let url = urlComponents?.url else { return }
let session = URLSession.shared
session.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
do {
self.films = try JSONDecoder().decode(Films.self, from: data)
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print(error)
}
}.resume()
}
// MARK: - Cells
func configureCell(cell: FilmsCell, for indexPath: IndexPath) {
guard let search = self.films.search else { return }
let films = search[indexPath.row]
cell.titleFilmLabel.text = films.title
if let imageUrl = URL(string: films.poster!) {
DispatchQueue.global().async {
guard let data = try? Data(contentsOf: imageUrl) else { return }
let image = UIImage(data: data)
DispatchQueue.main.async {
cell.imageFilm.image = image
}
}
}
}
}
extension FilmsViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
getDate(title: searchController.searchBar.text!, page: page)
}
}
extension FilmsViewController: UITableViewDelegate {
}
extension FilmsViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let search = self.films.search else { return 20 }
return search.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FilmsCell
configureCell(cell: cell, for: indexPath)
return cell
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let search = self.films.search {
if indexPath.row == search.count - 1 {
page += 1
getDate(title: searchController.searchBar.text!, page: page)
}
}
}
}
Upvotes: 0
Views: 1796
Reputation: 1616
One of the good and efficient way to do it is by using scrollviewDelegate in tableview. Just add UIScrollViewDelegate in your viewController
//For Pagination
var isDataLoading:Bool=false
var pageNo:Int=0
var limit:Int=20
var offset:Int=0 //pageNo*limit
var didEndReached:Bool=false
override func viewDidLoad(_){
tableview.delegate=self //To enable scrollviewdelegate
}
ScrollView Delegate methods.
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
print("scrollViewWillBeginDragging")
isDataLoading = false
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
print("scrollViewDidEndDecelerating")
}
//Pagination
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
print("scrollViewDidEndDragging")
if ((tableView.contentOffset.y + tableView.frame.size.height) >= tableView.contentSize.height)
{
if !isDataLoading{
isDataLoading = true
self.pageNo=self.pageNo+1
self.limit=self.limit+10
self.offset=self.limit * self.pageNo
loadCallLogData(offset: self.offset, limit: self.limit)
}
}
}
Upvotes: 0
Reputation: 64
This useful way i do it in all my project. when the user reach the end of the tableview i call the api to fetch data.
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
let height = scrollView.frame.size.height
let contentYoffset = scrollView.contentOffset.y
let distanceFromBottom = scrollView.contentSize.height - contentYoffset
if distanceFromBottom < height { // when you reach the bottom
page += 1
getDate(title: searchController.searchBar.text!, page: page)
}
}
Upvotes: 1