Home > Software design >  How to Increase count of Page in Url for loading more data and show indicator at bottom?
How to Increase count of Page in Url for loading more data and show indicator at bottom?

Time:01-12

I Creating a demo of webservices, In this I want to increase page count and load more data from api, and add in table view after activity indicator refreshing. I find many tutorials but Not found useful... They are all Advance and I'm beginner so i didn't get properly. Can Any one please tell how to do this.

Here's My Demo details...

This Is Page Count of URL

 "info": {
    "count": 826,
    "pages": 42,
    "next": "https://rickandmortyapi.com/api/character/?page=3",
    "prev": "https://rickandmortyapi.com/api/character/?page=1"
  },

My json Model

import UIKit
import Foundation

// MARK: - JsonModel
struct JSONModel:Decodable {
let info: Info
let results: [Result]
}

// MARK: - Info
 struct Info : Decodable {
let count, pages: Int
let next: String
let prev: NSNull
 }

  // MARK: - Result
 struct Result : Decodable {
let id: Int
let name: String
let status: Status
let species: Species
let type: String
let gender: Gender
let origin, location: Location
let image: String
let episode: [String]
let url: String
let created: String
 }

enum Gender {
case female
case male
case unknown
 }

// MARK: - Location
struct Location {
let name: String
let url: String
 }

enum Species {
case alien
case human
}

enum Status {
case alive
case dead
case unknown
 }

This is my View controller Class

import UIKit
import Kingfisher

class ViewController: UIViewController,UISearchBarDelegate{



@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var tableView: UITableView!

var results = [Results]()
var filteredData = [Results]()
var batchSize = 42
var fromIndex = 0

override func viewDidLoad() {
    super.viewDidLoad()
    searchBar.delegate = self
    tableView.delegate = self
    tableView.dataSource = self
    apiCalling()
    filteredData = results
    
}

override func viewWillAppear(_ animated: Bool) {
    filteredData = results
    self.tableView.reloadData()
}


func apiCalling(){
    
    
    guard let url = URL(string: "https://rickandmortyapi.com/api/character/") else { return }
    URLSession.shared.dataTask(with: url) {[weak self]data, response, error in
        
        
        if error != nil{
            print("error While Fetching Data")
        }
        
        guard let data = data else {
            return
        }
        do {
            let resultData = try JSONDecoder().decode(JsonModel.self, from: data)
            self?.results = resultData.results!
            self?.filteredData = self!.results
            DispatchQueue.main.async {
                self?.tableView.reloadData()
            }
          
        } catch  {
            print(error.localizedDescription)
        }
    }.resume()

}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
   
    let searchText = searchBar.text!
    guard !searchText.isEmpty else {
        filteredData = results
        tableView.reloadData()
        return
    }
    filteredData = results.filter({ $0.name!.lowercased().contains(searchText.lowercased() ) })
    tableView.reloadData()


    }





func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
        self.searchBar.showsCancelButton = true
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.showsCancelButton = false
        searchBar.text = ""
        searchBar.resignFirstResponder()
        filteredData.removeAll()
        self.tableView.reloadData()
   }


 }

This My Tableview Extension

extension ViewController : UITableViewDelegate, UITableViewDataSource  {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return filteredData.count 
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! UserTableViewCell
    let row = filteredData[indexPath.row]
    let imageUrl = URL(string: row.image!)
    cell.userImage.kf.setImage(with: imageUrl)
    cell.lblGender.text = "Gender:- \(row.gender ?? "no value")"
    cell.lblID.text = "ID:- \(row.id ?? 0)"
    cell.lblName.text = "Name: \(row.name!)"
    cell.lblSpecies.text = "Species:- \(row.species ?? "No Speies")"
    return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
    
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return 250
}
}

CodePudding user response:

u need save page info.

self?.info = resultData.info!

call "loadpage" when u loading more data

override func viewDidLoad() {
    super.viewDidLoad()
    searchBar.delegate = self
    tableView.delegate = self
    tableView.dataSource = self
    filteredData = []
    result = []
    apiCalling(apiurl:"https://rickandmortyapi.com/api/character/")
}

func apiCalling(apiurl:String){
    
    
    guard let url = URL(string: apiurl) else { return }
    URLSession.shared.dataTask(with: url) {[weak self]data, response, error in
        
        
        if error != nil{
            print("error While Fetching Data")
        }
        
        guard let data = data else {
            return
        }
        do {
            let resultData = try JSONDecoder().decode(JsonModel.self, from: data)
            self?.results.append(resultData.results!)
            self?.info = resultData.info!
            filterWord()
          
        } catch  {
            print(error.localizedDescription)
        }
    }.resume()

}

func filterWord(){
    let searchText = searchBar.text!
    guard !searchText.isEmpty else {
        filteredData = results
        tableView.reloadData()
        return
    }
    filteredData = results.filter({ $0.name!.lowercased().contains(searchText.lowercased() ) })
    tableView.reloadData()
}

func loadPage(){
    guard let page = self?.info.next,!page.isEmpty else{
        return
    }
    apiCalling(apiurl:page)
}

under indicator simple example like this

func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
    guard let page = self?.info.next,!page.isEmpty else{
        return nil
    }
    //press to call loadPage
    let loading = UIButton.init()
    let view = UIView.init()
    view.addSubview(loading)
    return view
}

CodePudding user response:

I'm Giving My own Questions answer Here...

I Have Create 3 more variables

 var curentIndex : Int = 0
// I'm Putting Default Limit Here...
var numberArray = Array(1...42)
var fetchingMore = false

Api Call

func apiCalling(){
    guard !fetchingMore else  {
        print("Didn't call Get Data")
        return
    }
    
    fetchingMore = true
    guard let url = URL( string: "\(baseUrl)?page=\(numberArray[curentIndex])") ?? URL(string: "" ) else {
        fetchingMore = false
        return
    }
    
    curentIndex  = 1
    URLSession.shared.dataTask(with: url) {[weak self]data, response, error in
        if error != nil{
            print("error While Fetching Data")
        }
        guard let data = data else {
            return
        }
        do {
            let resultData = try JSONDecoder().decode(JsonModel.self, from: data)
            self?.results  = resultData.results!
            self?.filteredData = self!.results
            DispatchQueue.main.async {
                self?.tableView.reloadData()
            }
        } catch  {
            print(error.localizedDescription)
        }
        self?.fetchingMore = false
    }.resume()
}

**Here's My CellForRowMethod **

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! UserTableViewCell
    let row = filteredData[indexPath.row]
    if indexPath.row == filteredData.count - 1 && curentIndex <= row.id ?? 0 {
        apiCalling()
    }
    let imageUrl = URL(string: row.image!)
    cell.userImage.kf.setImage(with: imageUrl)
    cell.lblGender.text = "Gender:- \(row.gender ?? "no value")"
    cell.lblID.text = "ID:- \(row.id ?? 0)"
    cell.lblName.text = "Name: \(row.name!)"
    cell.lblSpecies.text = "Species:- \(row.species ?? "No Speies")"
    return cell
}
  •  Tags:  
  • Related