Pagination Data Fetch
AppStore JSON APIs
Let's wrap up this bonus feature by going over how to initiate our data fetches while we are scrolling to the bottom of our list. The great thing about the iTunes Search API is that they allow us to provide offsets are search limits through our url request. This is a frequently requested feature so let me show you an easy way of implementing this.

Comments (13)
CartJolly
4 years ago
Hi Brian, Not a question about the course but will you be doing a course related to building a website like the one you made for yourself? I would be super interested in a React course, you have a nice website layout.
nombienombie
4 years ago
You should check Brian's YouTube. I believe he has a course on ReactJS which if I recall correctly, this site is built in.
CartJolly
4 years ago
Thank you!!
Dennisvm82
4 years ago
I prefer the following code to create a delay for the indicator, because the sleep functionality automatically blocks everything else on that thread as well. For this lesson it didn't really matter, but for bigger applications it's not advised to put everything to sleep just to add a delay to a single view :-) what about a bonus lesson to implement touch id? DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { self.results += searchResult?.results ?? [] DispatchQueue.main.async { self.collectionView.reloadData() } }
Brian Voong
4 years ago
weare99
4 years ago
Hi Brian why you don't use property observers like didSet? After setting the array?
Brian Voong
4 years ago
PreachOnBerto
4 years ago
Hey Brian, have you ever used UICollectionViewDataSourcePrefetching for pagination?
Brian Voong
4 years ago
PreachOnBerto
4 years ago
Yeah I've seen examples, but nothing on how to apply it to an API that allows for limits and offset parameters. No sure if using that protocol would make much of a difference.
Brian Voong
4 years ago
PreachOnBerto
4 years ago
That'd be awesome! I did play around with it a couple weeks back trying to understand it and get it working but not luck so I ended up going with an implementation similar to the one in this video.
Sebastien Menozzi
4 years ago
Hey Brian, I don't know exactly how works the iTunes API, but I think that the "isDonePaginating" variable should be set to true when this condition => results.count % limit != 0 || results.count == 0 is equal to true.
Brian Voong
4 years ago
chao700716
4 years ago
I guess the logic to initiate pagination might also need to consider the logic of "isDonePaginating". In other words, "if indexPath.item == results.count - 1 && !isPaginating" might need to be changed to "if indexPath.item == results.count - 1 && !isPaginating && !isDonePaginating". Otherwise, the last fetched data seems to be appended to the array "results" repetitively.
RoomDig
4 years ago
hi guys i'm running circles trying to implement pagination so i've got a rest api that returns 10 results at a time inside of the return there is a nextUrl and prevUrl specified. I preset isPaginating to false. Basically what happens is immediately after the first data fetch is complete my pagination get's initiated right away without me ever scrolling on the table view can anyone shed some light on what may be causing this? Here's what i have: func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "HousingTableViewCell", for: indexPath) as! HousingTableViewCell let listing = houses[indexPath.row] cell.priceLabel.text = "$\(listing.monthly_price)" cell.likeLabel.text = "\(listing.likeCount)" cell.bedsAvailLabel.text = "\(listing.beds_avail)" cell.numBathsLabel.text = "\(listing.num_baths)" cell.leaseLengthLabel.text = listing.term == "long" ? "\(listing.duration) months" : "\(listing.duration) days" cell.termLabel.text = listing.term == "long" ? "Long Term" : "Short Term" var imageInputs = [AlamofireSource]() cell.testingSlideShow.contentScaleMode = UIView.ContentMode.scaleAspectFill listing.images.forEach { (img) in imageInputs.append(AlamofireSource(urlString: img.url)!) } cell.testingSlideShow.setImageInputs(imageInputs) // initiate pagination if indexPath.row == houses.count - 1 && !isPaginating && nextHousesUrl != "" { print("indexpath:", indexPath.row) print("Paginating data from:", self.nextHousesUrl) } return cell }
Brian Voong
4 years ago
RoomDig
4 years ago
That did the trick! I mean it still fires instantly with out me scrolling but it only fires once then i have to scroll to the bottom to get page 3! Thank you so much!
perfect.aduh@gmail.com
4 years ago
Brian, please be informed that I am not able to download the project
Brian Voong
4 years ago
perfect.aduh@gmail.com
4 years ago
It does not even start, rather it downloads a .html file and not the video
perfect.aduh@gmail.com
4 years ago
Sorry I meant and not the project
Brian Voong
4 years ago
perfect.aduh@gmail.com
4 years ago
The file is course_video.html
Brian Voong
4 years ago
perfect.aduh@gmail.com
4 years ago
I am actually on chrome. maybe will try firefox later on
perfect.aduh@gmail.com
4 years ago
The file is course_video.html
Stewart Lynch
4 years ago
Brian. I want to thank you for this course. I have always been a IB kind of guy, but now, I feel pretty confident in the ability to build out my UI in code. Your helper classes are great. One thing I would love to see you do in the future is to build a Universal app. One that will adjust the layout if running on an iPad. I mean more than just introducing a splitViewController, but rather getting into size classes, etc. I would love to see how you would do that in code.
Dariusd
4 years ago
Hi Brian, thank you for all of your great tutorials. I have a maybe rather difficult question regarding pagination. In my app I want to fetch items based on a ranking in decreasing/increasing order. However while fetching the data, obviously the data will change and the order of the ranking. For example an item could be ranked top 9 and now be moved to rank top 11 and I would fetch it twice if my limit is 10. Is it possible to paginate that kind of data in order somehow? This question really bothers me as it would be essential to the app I am developing.
Brian Voong
4 years ago
Dariusd
4 years ago
Thank you for quick response Brian! :)
Sandeep
4 years ago
Hi Brian, I have a uicollectionview where i fetch new data from API, and then insert in collectioview, after inserting its scroll position changes and it scrolls up, how to maintain the scroll position after inserting cell? please help. Below is the code for reference APIRequest.shared().fetchAgewiseSearch(params: params) { [unowned self] (urlResponse, data, error) in if let error = error { print("error fetching candidates", error) } if let data = data { do { let response = try jsonDecoder.decode(AgewiseSearchResponse.self, from: data) if response.candidates.count == 0 { self.isDonePaginating = true } //self.items += response.candidates self.bottomOffset += self.collectionView.contentSize.height - self.collectionView.contentOffset.y CATransaction.begin() CATransaction.setDisableActions(true) self.collectionView.performBatchUpdates({ for i in 0..<response.candidates.count { self.items.append(response.candidates[i]) let indexPath = IndexPath(item: self.items.count - 1, section: 0) self.collectionView.insertItems(at: [indexPath]) } }, completion: { (success) in //self.collectionView.contentSize.height - bottomOffset let offset = CGPoint(x: 0, y: self.bottomOffset) self.collectionView.setContentOffset(offset, animated: false) //self.bottomOffset += self.collectionView.contentSize.height //self.collectionView.contentOffset = CGPoint(x: 0, y: self.collectionView.contentSize.height - self.bottomOffset) self.stopIndex = response.stopIndex self.lastIndex = response.lastIndex self.isPaginating = false self.collectionView.collectionViewLayout.invalidateLayout() self.collectionView.layoutSubviews() CATransaction.commit() }) } catch { print("error parsing candidats", error) } } }
Brian Voong
4 years ago
Sandeep
3 years ago
Hey Brain, Earlier i coded as per lesson but didn't work out its scroll position still changes for me. I guess its because my cell size are dynamic (self-sizing cell) thats the issue. In the lesson above cell size are fixed and when i tried with fixed size it worked well without any issue. If any suggestion on dynamic size will be helpful. "Side note: I believe your sample code is something used in 2014-2015 era of ios development". Yes i got the reference from here, so i gave it a try https://stackoverflow.com/questions/25548257/uicollectionview-insert-cells-above-maintaining-position-like-messages-app/34192787 Thank you Brian for response and the awesome course.
RichyCode
3 years ago
Hi Brian, any plans to add pagination whilst using a diffable data source ? Can’t seem to get My head round how you would implement this Fine when just using a regular cell and returning the count - 1 , looks complex for a dds Any thoughts on where to start ? Thanks
RichyCode
3 years ago
I ve managed to implement this if anyone needs the code let me know
David Hurd
3 years ago
I've been curious about pagination with a diffable data source. Could you share the solution you came up with? Thanks.
HELP & SUPPORT