Swift 4 tableView API Pagination





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I have successfully parsed and decoded the JSON data and it displays in the console. I don't know how I would set up pagination with the api and display all of the data when I scroll down on the tableView. The API I'm using is https://rickandmortyapi.com/api/character/. Thank you for all your help in advance!



This is the code in my main ViewController



import UIKit

struct PagedCharacters: Codable {
struct Info: Codable {
let count: Int
let pages: Int
let next: String
let prev: String
}

struct Results: Codable {
let name: String
let status: String
let species: String
}

let info: Info
let results: [Results]

}


class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var uiTableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
getRickAndMortyData()


self.uiTableView.dataSource = self
self.uiTableView.delegate = self

// Do any additional setup after loading the view.
}

func getRickAndMortyData() {

//create instance of the url
let url = "https://rickandmortyapi.com/api/character/"

//construct the url, use guard to avoid nonoptional
guard let urlObj = URL(string: url) else
{ return }

//fetch data
URLSession.shared.dataTask(with: urlObj) {(data, response, error) in

//to avoid non optional in JSONDecoder
guard let data = data else { return }

do {
//decode object
let downloadedRickAndMorty = try JSONDecoder().decode(PagedCharacters.self, from: data)
DispatchQueue.main.async {
self.uiTableView.reloadData()
}
print(downloadedRickAndMorty)

} catch {
print(error)

}

}.resume()

}


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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "rickandmortyCell") as? CharacterTableViewCell else { return UITableViewCell() }

cell.nameLabel.text = "Name: " + PagedCharacters.Results[indexPath.row].name

return cell
}


}


This is my tableviewcell class



import UIKit

class CharacterTableViewCell: UITableViewCell {

@IBOutlet weak var nameLabel: UILabel!


override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)

// Configure the view for the selected state
}

}


This is the data I'm getting in my console when the parsed data is printed. I'm still not getting all the data from the different pages.




PagedCharacters(info: API_Practice.PagedCharacters.Info(count: 493,
pages: 25, next: "https://rickandmortyapi.com/api/character/?page=2",
prev: ""), results: [API_Practice.PagedCharacters.Results(name: "Rick
Sanchez", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Morty Smith", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Summer Smith", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Beth Smith", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Jerry Smith", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Abadango Cluster
Princess", status: "Alive", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Abradolf Lincler", status:
"unknown", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Adjudicator Rick", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Agency Director", status: "Dead", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Alan Rails", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Albert Einstein", status: "Dead", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Alexander", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Alien Googah", status: "unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Alien Morty", status:
"unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Alien Rick", status:
"unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Amish Cyborg", status:
"Dead", species: "Alien"), API_Practice.PagedCharacters.Results(name:
"Annie", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Antenna Morty", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Antenna Rick", status: "unknown", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Ants in my Eyes Johnson",
status: "unknown", species: "Human")])




If you need anything else please let me know. Thank you!










share|improve this question

























  • stackoverflow.com/questions/34588837/…

    – Abdulaziz.Musaileekh
    Nov 28 '18 at 4:38


















0















I have successfully parsed and decoded the JSON data and it displays in the console. I don't know how I would set up pagination with the api and display all of the data when I scroll down on the tableView. The API I'm using is https://rickandmortyapi.com/api/character/. Thank you for all your help in advance!



This is the code in my main ViewController



import UIKit

struct PagedCharacters: Codable {
struct Info: Codable {
let count: Int
let pages: Int
let next: String
let prev: String
}

struct Results: Codable {
let name: String
let status: String
let species: String
}

let info: Info
let results: [Results]

}


class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var uiTableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
getRickAndMortyData()


self.uiTableView.dataSource = self
self.uiTableView.delegate = self

// Do any additional setup after loading the view.
}

func getRickAndMortyData() {

//create instance of the url
let url = "https://rickandmortyapi.com/api/character/"

//construct the url, use guard to avoid nonoptional
guard let urlObj = URL(string: url) else
{ return }

//fetch data
URLSession.shared.dataTask(with: urlObj) {(data, response, error) in

//to avoid non optional in JSONDecoder
guard let data = data else { return }

do {
//decode object
let downloadedRickAndMorty = try JSONDecoder().decode(PagedCharacters.self, from: data)
DispatchQueue.main.async {
self.uiTableView.reloadData()
}
print(downloadedRickAndMorty)

} catch {
print(error)

}

}.resume()

}


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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "rickandmortyCell") as? CharacterTableViewCell else { return UITableViewCell() }

cell.nameLabel.text = "Name: " + PagedCharacters.Results[indexPath.row].name

return cell
}


}


This is my tableviewcell class



import UIKit

class CharacterTableViewCell: UITableViewCell {

@IBOutlet weak var nameLabel: UILabel!


override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)

// Configure the view for the selected state
}

}


This is the data I'm getting in my console when the parsed data is printed. I'm still not getting all the data from the different pages.




PagedCharacters(info: API_Practice.PagedCharacters.Info(count: 493,
pages: 25, next: "https://rickandmortyapi.com/api/character/?page=2",
prev: ""), results: [API_Practice.PagedCharacters.Results(name: "Rick
Sanchez", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Morty Smith", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Summer Smith", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Beth Smith", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Jerry Smith", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Abadango Cluster
Princess", status: "Alive", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Abradolf Lincler", status:
"unknown", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Adjudicator Rick", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Agency Director", status: "Dead", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Alan Rails", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Albert Einstein", status: "Dead", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Alexander", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Alien Googah", status: "unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Alien Morty", status:
"unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Alien Rick", status:
"unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Amish Cyborg", status:
"Dead", species: "Alien"), API_Practice.PagedCharacters.Results(name:
"Annie", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Antenna Morty", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Antenna Rick", status: "unknown", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Ants in my Eyes Johnson",
status: "unknown", species: "Human")])




If you need anything else please let me know. Thank you!










share|improve this question

























  • stackoverflow.com/questions/34588837/…

    – Abdulaziz.Musaileekh
    Nov 28 '18 at 4:38














0












0








0


0






I have successfully parsed and decoded the JSON data and it displays in the console. I don't know how I would set up pagination with the api and display all of the data when I scroll down on the tableView. The API I'm using is https://rickandmortyapi.com/api/character/. Thank you for all your help in advance!



This is the code in my main ViewController



import UIKit

struct PagedCharacters: Codable {
struct Info: Codable {
let count: Int
let pages: Int
let next: String
let prev: String
}

struct Results: Codable {
let name: String
let status: String
let species: String
}

let info: Info
let results: [Results]

}


class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var uiTableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
getRickAndMortyData()


self.uiTableView.dataSource = self
self.uiTableView.delegate = self

// Do any additional setup after loading the view.
}

func getRickAndMortyData() {

//create instance of the url
let url = "https://rickandmortyapi.com/api/character/"

//construct the url, use guard to avoid nonoptional
guard let urlObj = URL(string: url) else
{ return }

//fetch data
URLSession.shared.dataTask(with: urlObj) {(data, response, error) in

//to avoid non optional in JSONDecoder
guard let data = data else { return }

do {
//decode object
let downloadedRickAndMorty = try JSONDecoder().decode(PagedCharacters.self, from: data)
DispatchQueue.main.async {
self.uiTableView.reloadData()
}
print(downloadedRickAndMorty)

} catch {
print(error)

}

}.resume()

}


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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "rickandmortyCell") as? CharacterTableViewCell else { return UITableViewCell() }

cell.nameLabel.text = "Name: " + PagedCharacters.Results[indexPath.row].name

return cell
}


}


This is my tableviewcell class



import UIKit

class CharacterTableViewCell: UITableViewCell {

@IBOutlet weak var nameLabel: UILabel!


override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)

// Configure the view for the selected state
}

}


This is the data I'm getting in my console when the parsed data is printed. I'm still not getting all the data from the different pages.




PagedCharacters(info: API_Practice.PagedCharacters.Info(count: 493,
pages: 25, next: "https://rickandmortyapi.com/api/character/?page=2",
prev: ""), results: [API_Practice.PagedCharacters.Results(name: "Rick
Sanchez", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Morty Smith", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Summer Smith", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Beth Smith", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Jerry Smith", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Abadango Cluster
Princess", status: "Alive", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Abradolf Lincler", status:
"unknown", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Adjudicator Rick", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Agency Director", status: "Dead", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Alan Rails", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Albert Einstein", status: "Dead", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Alexander", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Alien Googah", status: "unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Alien Morty", status:
"unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Alien Rick", status:
"unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Amish Cyborg", status:
"Dead", species: "Alien"), API_Practice.PagedCharacters.Results(name:
"Annie", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Antenna Morty", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Antenna Rick", status: "unknown", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Ants in my Eyes Johnson",
status: "unknown", species: "Human")])




If you need anything else please let me know. Thank you!










share|improve this question
















I have successfully parsed and decoded the JSON data and it displays in the console. I don't know how I would set up pagination with the api and display all of the data when I scroll down on the tableView. The API I'm using is https://rickandmortyapi.com/api/character/. Thank you for all your help in advance!



This is the code in my main ViewController



import UIKit

struct PagedCharacters: Codable {
struct Info: Codable {
let count: Int
let pages: Int
let next: String
let prev: String
}

struct Results: Codable {
let name: String
let status: String
let species: String
}

let info: Info
let results: [Results]

}


class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var uiTableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
getRickAndMortyData()


self.uiTableView.dataSource = self
self.uiTableView.delegate = self

// Do any additional setup after loading the view.
}

func getRickAndMortyData() {

//create instance of the url
let url = "https://rickandmortyapi.com/api/character/"

//construct the url, use guard to avoid nonoptional
guard let urlObj = URL(string: url) else
{ return }

//fetch data
URLSession.shared.dataTask(with: urlObj) {(data, response, error) in

//to avoid non optional in JSONDecoder
guard let data = data else { return }

do {
//decode object
let downloadedRickAndMorty = try JSONDecoder().decode(PagedCharacters.self, from: data)
DispatchQueue.main.async {
self.uiTableView.reloadData()
}
print(downloadedRickAndMorty)

} catch {
print(error)

}

}.resume()

}


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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "rickandmortyCell") as? CharacterTableViewCell else { return UITableViewCell() }

cell.nameLabel.text = "Name: " + PagedCharacters.Results[indexPath.row].name

return cell
}


}


This is my tableviewcell class



import UIKit

class CharacterTableViewCell: UITableViewCell {

@IBOutlet weak var nameLabel: UILabel!


override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)

// Configure the view for the selected state
}

}


This is the data I'm getting in my console when the parsed data is printed. I'm still not getting all the data from the different pages.




PagedCharacters(info: API_Practice.PagedCharacters.Info(count: 493,
pages: 25, next: "https://rickandmortyapi.com/api/character/?page=2",
prev: ""), results: [API_Practice.PagedCharacters.Results(name: "Rick
Sanchez", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Morty Smith", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Summer Smith", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Beth Smith", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Jerry Smith", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Abadango Cluster
Princess", status: "Alive", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Abradolf Lincler", status:
"unknown", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Adjudicator Rick", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Agency Director", status: "Dead", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Alan Rails", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Albert Einstein", status: "Dead", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Alexander", status:
"Dead", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Alien Googah", status: "unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Alien Morty", status:
"unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Alien Rick", status:
"unknown", species: "Alien"),
API_Practice.PagedCharacters.Results(name: "Amish Cyborg", status:
"Dead", species: "Alien"), API_Practice.PagedCharacters.Results(name:
"Annie", status: "Alive", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Antenna Morty", status:
"Alive", species: "Human"), API_Practice.PagedCharacters.Results(name:
"Antenna Rick", status: "unknown", species: "Human"),
API_Practice.PagedCharacters.Results(name: "Ants in my Eyes Johnson",
status: "unknown", species: "Human")])




If you need anything else please let me know. Thank you!







api uitableview pagination swift4






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 23 '18 at 2:04







newToIosProgramming

















asked Nov 22 '18 at 21:37









newToIosProgrammingnewToIosProgramming

32




32













  • stackoverflow.com/questions/34588837/…

    – Abdulaziz.Musaileekh
    Nov 28 '18 at 4:38



















  • stackoverflow.com/questions/34588837/…

    – Abdulaziz.Musaileekh
    Nov 28 '18 at 4:38

















stackoverflow.com/questions/34588837/…

– Abdulaziz.Musaileekh
Nov 28 '18 at 4:38





stackoverflow.com/questions/34588837/…

– Abdulaziz.Musaileekh
Nov 28 '18 at 4:38












1 Answer
1






active

oldest

votes


















0














There were many flaws in your logic, so I have rewritten it with minimal changes. Now it will serve your purpose.



import UIKit
struct PagedCharacters: Codable {
let info: Info
let results: [Results]

}
struct Info: Codable {
let count: Int
let pages: Int
let next: String
let prev: String
}

struct Results: Codable {
let name: String
let status: String
let species: String
}


And here is the code for view controller class:



class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var uiTableView: UITableView!
var aryDownloadedData:[Results]?
var nextPageUrl:String!

override func viewDidLoad() {
super.viewDidLoad()
getIntitalRickAndMortyData()


self.uiTableView.dataSource = self
self.uiTableView.delegate = self

// Do any additional setup after loading the view.
}
func getIntitalRickAndMortyData(){
aryDownloadedData =
//here first page is next page
nextPageUrl = "https://rickandmortyapi.com/api/character/"
getRickAndMortyData()
}

func getRickAndMortyData() {

//construct the url, use guard to avoid nonoptional
guard let urlObj = URL(string: nextPageUrl) else
{ return }

//fetch data
URLSession.shared.dataTask(with: urlObj) {[weak self](data, response, error) in

//to avoid non optional in JSONDecoder
guard let data = data else { return }

do {
//decode object
let downloadedRickAndMorty = try JSONDecoder().decode(PagedCharacters.self, from: data)
self?.aryDownloadedData?.append(contentsOf: downloadedRickAndMorty.results)
self?.nextPageUrl = downloadedRickAndMorty.info.next

DispatchQueue.main.async {
self?.uiTableView.reloadData()
}
print(self?.aryDownloadedData as Any)

} catch {
print(error)

}

}.resume()

}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.aryDownloadedData?.count ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if let count = aryDownloadedData?.count, count>1{
let lastElement = count - 1
if indexPath.row == lastElement {
//call get api for next page
getRickAndMortyData()
}
}

guard let cell = tableView.dequeueReusableCell(withIdentifier: "rickandmortyCell") as? CharacterTableViewCell else { return UITableViewCell() }

cell.nameLabel.text = "Name: " + (self.aryDownloadedData?[indexPath.row].name ?? "default")

return cell
}
}





share|improve this answer


























  • @AaronTreinish : if this is the solution you are looking for, please up vote and accept the answer. Thanks 😊

    – nikksindia
    Dec 11 '18 at 3:00











  • The code still only gets the data from the first page and not the other pages. Is there something else I have to do to get the data from the other pages?

    – newToIosProgramming
    Dec 12 '18 at 3:35











  • tableView(tableView: willDisplayCell:) does this for you. As soon as you reach the end of list, it will trigger api call with next page url.

    – nikksindia
    Dec 12 '18 at 5:38











  • I ran the code as you have it and when I scroll to the bottom it doesn't trigger the api call with the next page url. It just has the initial page on the tableview.

    – newToIosProgramming
    Dec 12 '18 at 15:27













  • @AaronTreinish: I have updated the code. Check now

    – nikksindia
    Dec 13 '18 at 6:07












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53438239%2fswift-4-tableview-api-pagination%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














There were many flaws in your logic, so I have rewritten it with minimal changes. Now it will serve your purpose.



import UIKit
struct PagedCharacters: Codable {
let info: Info
let results: [Results]

}
struct Info: Codable {
let count: Int
let pages: Int
let next: String
let prev: String
}

struct Results: Codable {
let name: String
let status: String
let species: String
}


And here is the code for view controller class:



class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var uiTableView: UITableView!
var aryDownloadedData:[Results]?
var nextPageUrl:String!

override func viewDidLoad() {
super.viewDidLoad()
getIntitalRickAndMortyData()


self.uiTableView.dataSource = self
self.uiTableView.delegate = self

// Do any additional setup after loading the view.
}
func getIntitalRickAndMortyData(){
aryDownloadedData =
//here first page is next page
nextPageUrl = "https://rickandmortyapi.com/api/character/"
getRickAndMortyData()
}

func getRickAndMortyData() {

//construct the url, use guard to avoid nonoptional
guard let urlObj = URL(string: nextPageUrl) else
{ return }

//fetch data
URLSession.shared.dataTask(with: urlObj) {[weak self](data, response, error) in

//to avoid non optional in JSONDecoder
guard let data = data else { return }

do {
//decode object
let downloadedRickAndMorty = try JSONDecoder().decode(PagedCharacters.self, from: data)
self?.aryDownloadedData?.append(contentsOf: downloadedRickAndMorty.results)
self?.nextPageUrl = downloadedRickAndMorty.info.next

DispatchQueue.main.async {
self?.uiTableView.reloadData()
}
print(self?.aryDownloadedData as Any)

} catch {
print(error)

}

}.resume()

}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.aryDownloadedData?.count ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if let count = aryDownloadedData?.count, count>1{
let lastElement = count - 1
if indexPath.row == lastElement {
//call get api for next page
getRickAndMortyData()
}
}

guard let cell = tableView.dequeueReusableCell(withIdentifier: "rickandmortyCell") as? CharacterTableViewCell else { return UITableViewCell() }

cell.nameLabel.text = "Name: " + (self.aryDownloadedData?[indexPath.row].name ?? "default")

return cell
}
}





share|improve this answer


























  • @AaronTreinish : if this is the solution you are looking for, please up vote and accept the answer. Thanks 😊

    – nikksindia
    Dec 11 '18 at 3:00











  • The code still only gets the data from the first page and not the other pages. Is there something else I have to do to get the data from the other pages?

    – newToIosProgramming
    Dec 12 '18 at 3:35











  • tableView(tableView: willDisplayCell:) does this for you. As soon as you reach the end of list, it will trigger api call with next page url.

    – nikksindia
    Dec 12 '18 at 5:38











  • I ran the code as you have it and when I scroll to the bottom it doesn't trigger the api call with the next page url. It just has the initial page on the tableview.

    – newToIosProgramming
    Dec 12 '18 at 15:27













  • @AaronTreinish: I have updated the code. Check now

    – nikksindia
    Dec 13 '18 at 6:07
















0














There were many flaws in your logic, so I have rewritten it with minimal changes. Now it will serve your purpose.



import UIKit
struct PagedCharacters: Codable {
let info: Info
let results: [Results]

}
struct Info: Codable {
let count: Int
let pages: Int
let next: String
let prev: String
}

struct Results: Codable {
let name: String
let status: String
let species: String
}


And here is the code for view controller class:



class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var uiTableView: UITableView!
var aryDownloadedData:[Results]?
var nextPageUrl:String!

override func viewDidLoad() {
super.viewDidLoad()
getIntitalRickAndMortyData()


self.uiTableView.dataSource = self
self.uiTableView.delegate = self

// Do any additional setup after loading the view.
}
func getIntitalRickAndMortyData(){
aryDownloadedData =
//here first page is next page
nextPageUrl = "https://rickandmortyapi.com/api/character/"
getRickAndMortyData()
}

func getRickAndMortyData() {

//construct the url, use guard to avoid nonoptional
guard let urlObj = URL(string: nextPageUrl) else
{ return }

//fetch data
URLSession.shared.dataTask(with: urlObj) {[weak self](data, response, error) in

//to avoid non optional in JSONDecoder
guard let data = data else { return }

do {
//decode object
let downloadedRickAndMorty = try JSONDecoder().decode(PagedCharacters.self, from: data)
self?.aryDownloadedData?.append(contentsOf: downloadedRickAndMorty.results)
self?.nextPageUrl = downloadedRickAndMorty.info.next

DispatchQueue.main.async {
self?.uiTableView.reloadData()
}
print(self?.aryDownloadedData as Any)

} catch {
print(error)

}

}.resume()

}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.aryDownloadedData?.count ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if let count = aryDownloadedData?.count, count>1{
let lastElement = count - 1
if indexPath.row == lastElement {
//call get api for next page
getRickAndMortyData()
}
}

guard let cell = tableView.dequeueReusableCell(withIdentifier: "rickandmortyCell") as? CharacterTableViewCell else { return UITableViewCell() }

cell.nameLabel.text = "Name: " + (self.aryDownloadedData?[indexPath.row].name ?? "default")

return cell
}
}





share|improve this answer


























  • @AaronTreinish : if this is the solution you are looking for, please up vote and accept the answer. Thanks 😊

    – nikksindia
    Dec 11 '18 at 3:00











  • The code still only gets the data from the first page and not the other pages. Is there something else I have to do to get the data from the other pages?

    – newToIosProgramming
    Dec 12 '18 at 3:35











  • tableView(tableView: willDisplayCell:) does this for you. As soon as you reach the end of list, it will trigger api call with next page url.

    – nikksindia
    Dec 12 '18 at 5:38











  • I ran the code as you have it and when I scroll to the bottom it doesn't trigger the api call with the next page url. It just has the initial page on the tableview.

    – newToIosProgramming
    Dec 12 '18 at 15:27













  • @AaronTreinish: I have updated the code. Check now

    – nikksindia
    Dec 13 '18 at 6:07














0












0








0







There were many flaws in your logic, so I have rewritten it with minimal changes. Now it will serve your purpose.



import UIKit
struct PagedCharacters: Codable {
let info: Info
let results: [Results]

}
struct Info: Codable {
let count: Int
let pages: Int
let next: String
let prev: String
}

struct Results: Codable {
let name: String
let status: String
let species: String
}


And here is the code for view controller class:



class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var uiTableView: UITableView!
var aryDownloadedData:[Results]?
var nextPageUrl:String!

override func viewDidLoad() {
super.viewDidLoad()
getIntitalRickAndMortyData()


self.uiTableView.dataSource = self
self.uiTableView.delegate = self

// Do any additional setup after loading the view.
}
func getIntitalRickAndMortyData(){
aryDownloadedData =
//here first page is next page
nextPageUrl = "https://rickandmortyapi.com/api/character/"
getRickAndMortyData()
}

func getRickAndMortyData() {

//construct the url, use guard to avoid nonoptional
guard let urlObj = URL(string: nextPageUrl) else
{ return }

//fetch data
URLSession.shared.dataTask(with: urlObj) {[weak self](data, response, error) in

//to avoid non optional in JSONDecoder
guard let data = data else { return }

do {
//decode object
let downloadedRickAndMorty = try JSONDecoder().decode(PagedCharacters.self, from: data)
self?.aryDownloadedData?.append(contentsOf: downloadedRickAndMorty.results)
self?.nextPageUrl = downloadedRickAndMorty.info.next

DispatchQueue.main.async {
self?.uiTableView.reloadData()
}
print(self?.aryDownloadedData as Any)

} catch {
print(error)

}

}.resume()

}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.aryDownloadedData?.count ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if let count = aryDownloadedData?.count, count>1{
let lastElement = count - 1
if indexPath.row == lastElement {
//call get api for next page
getRickAndMortyData()
}
}

guard let cell = tableView.dequeueReusableCell(withIdentifier: "rickandmortyCell") as? CharacterTableViewCell else { return UITableViewCell() }

cell.nameLabel.text = "Name: " + (self.aryDownloadedData?[indexPath.row].name ?? "default")

return cell
}
}





share|improve this answer















There were many flaws in your logic, so I have rewritten it with minimal changes. Now it will serve your purpose.



import UIKit
struct PagedCharacters: Codable {
let info: Info
let results: [Results]

}
struct Info: Codable {
let count: Int
let pages: Int
let next: String
let prev: String
}

struct Results: Codable {
let name: String
let status: String
let species: String
}


And here is the code for view controller class:



class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var uiTableView: UITableView!
var aryDownloadedData:[Results]?
var nextPageUrl:String!

override func viewDidLoad() {
super.viewDidLoad()
getIntitalRickAndMortyData()


self.uiTableView.dataSource = self
self.uiTableView.delegate = self

// Do any additional setup after loading the view.
}
func getIntitalRickAndMortyData(){
aryDownloadedData =
//here first page is next page
nextPageUrl = "https://rickandmortyapi.com/api/character/"
getRickAndMortyData()
}

func getRickAndMortyData() {

//construct the url, use guard to avoid nonoptional
guard let urlObj = URL(string: nextPageUrl) else
{ return }

//fetch data
URLSession.shared.dataTask(with: urlObj) {[weak self](data, response, error) in

//to avoid non optional in JSONDecoder
guard let data = data else { return }

do {
//decode object
let downloadedRickAndMorty = try JSONDecoder().decode(PagedCharacters.self, from: data)
self?.aryDownloadedData?.append(contentsOf: downloadedRickAndMorty.results)
self?.nextPageUrl = downloadedRickAndMorty.info.next

DispatchQueue.main.async {
self?.uiTableView.reloadData()
}
print(self?.aryDownloadedData as Any)

} catch {
print(error)

}

}.resume()

}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.aryDownloadedData?.count ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if let count = aryDownloadedData?.count, count>1{
let lastElement = count - 1
if indexPath.row == lastElement {
//call get api for next page
getRickAndMortyData()
}
}

guard let cell = tableView.dequeueReusableCell(withIdentifier: "rickandmortyCell") as? CharacterTableViewCell else { return UITableViewCell() }

cell.nameLabel.text = "Name: " + (self.aryDownloadedData?[indexPath.row].name ?? "default")

return cell
}
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 13 '18 at 6:07

























answered Dec 4 '18 at 9:10









nikksindianikksindia

472412




472412













  • @AaronTreinish : if this is the solution you are looking for, please up vote and accept the answer. Thanks 😊

    – nikksindia
    Dec 11 '18 at 3:00











  • The code still only gets the data from the first page and not the other pages. Is there something else I have to do to get the data from the other pages?

    – newToIosProgramming
    Dec 12 '18 at 3:35











  • tableView(tableView: willDisplayCell:) does this for you. As soon as you reach the end of list, it will trigger api call with next page url.

    – nikksindia
    Dec 12 '18 at 5:38











  • I ran the code as you have it and when I scroll to the bottom it doesn't trigger the api call with the next page url. It just has the initial page on the tableview.

    – newToIosProgramming
    Dec 12 '18 at 15:27













  • @AaronTreinish: I have updated the code. Check now

    – nikksindia
    Dec 13 '18 at 6:07



















  • @AaronTreinish : if this is the solution you are looking for, please up vote and accept the answer. Thanks 😊

    – nikksindia
    Dec 11 '18 at 3:00











  • The code still only gets the data from the first page and not the other pages. Is there something else I have to do to get the data from the other pages?

    – newToIosProgramming
    Dec 12 '18 at 3:35











  • tableView(tableView: willDisplayCell:) does this for you. As soon as you reach the end of list, it will trigger api call with next page url.

    – nikksindia
    Dec 12 '18 at 5:38











  • I ran the code as you have it and when I scroll to the bottom it doesn't trigger the api call with the next page url. It just has the initial page on the tableview.

    – newToIosProgramming
    Dec 12 '18 at 15:27













  • @AaronTreinish: I have updated the code. Check now

    – nikksindia
    Dec 13 '18 at 6:07

















@AaronTreinish : if this is the solution you are looking for, please up vote and accept the answer. Thanks 😊

– nikksindia
Dec 11 '18 at 3:00





@AaronTreinish : if this is the solution you are looking for, please up vote and accept the answer. Thanks 😊

– nikksindia
Dec 11 '18 at 3:00













The code still only gets the data from the first page and not the other pages. Is there something else I have to do to get the data from the other pages?

– newToIosProgramming
Dec 12 '18 at 3:35





The code still only gets the data from the first page and not the other pages. Is there something else I have to do to get the data from the other pages?

– newToIosProgramming
Dec 12 '18 at 3:35













tableView(tableView: willDisplayCell:) does this for you. As soon as you reach the end of list, it will trigger api call with next page url.

– nikksindia
Dec 12 '18 at 5:38





tableView(tableView: willDisplayCell:) does this for you. As soon as you reach the end of list, it will trigger api call with next page url.

– nikksindia
Dec 12 '18 at 5:38













I ran the code as you have it and when I scroll to the bottom it doesn't trigger the api call with the next page url. It just has the initial page on the tableview.

– newToIosProgramming
Dec 12 '18 at 15:27







I ran the code as you have it and when I scroll to the bottom it doesn't trigger the api call with the next page url. It just has the initial page on the tableview.

– newToIosProgramming
Dec 12 '18 at 15:27















@AaronTreinish: I have updated the code. Check now

– nikksindia
Dec 13 '18 at 6:07





@AaronTreinish: I have updated the code. Check now

– nikksindia
Dec 13 '18 at 6:07




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53438239%2fswift-4-tableview-api-pagination%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

ComboBox Display Member on multiple fields

Is it possible to collect Nectar points via Trainline?