How to add Pagination with JSON data in collectionview in swift - ios

we need to pass count in JSON parameter like this
var currentPageNumberVM: Int = 0
"count": currentPageNumber
and in service call I'm getting JSON data like below here JSON data is coming and data is showing in collectionview but pagination is not working
func serviceCall(){
self.currentPageNumberVM+=10
let param = ["jsonrpc": "2.0",
"params": ["type" : type, "count": currentPageNumberVM]] as [String : Any]
APIReqeustManager.sharedInstance.serviceCall(param: param, vc: self, url: getUrl(of: .productByFeature), header: header) {(responseData) in
if responseData.error != nil{
self.view.makeToast(NSLocalizedString("Something went wrong!", comment: ""))
}else{
self.viewmoreDB = ViewMoreBase(dictionary: responseData.dict as NSDictionary? ?? NSDictionary())
self.productsData = self.viewmoreDB?.result?.products
self.collectionView.reloadData()
}
}
}
I'm adding values to collectionview like below
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return productsData?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HorizontalSliderCollectionCell", for: indexPath) as! HorizontalSliderCollectionCell
let indexData = productsData?[indexPath.item]
cell.lblDescrip.text = indexData?.product_by_language?.des
cell.lblTitle.text = indexData?.product_by_language?.title
return cell
}
for pagenation i am trying like below: but nothing works
var isLoading = false
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if (offsetY > contentHeight - scrollView.frame.height * 4) && !isLoading {
loadMoreData()
}
}
func loadMoreData() {
if !self.isLoading {
self.isLoading = true
DispatchQueue.global().async {
// Fake background loading task for 2 seconds
sleep(2)
// Download more data here
DispatchQueue.main.async {
self.collectionView.reloadData()
self.isLoading = false
}
}
}
}
How to add pagination to collectionview? .. I mean after loading 10 cells..below need to show activityindicator.. and load another 10 cells
how to do this, please do help me

Could you try this? but first, note that you need to pass the counter as a parameter in your call service function:
This code will be added in your cellForItemAt :
let lastPost = postsArray.count - 1
if lastPost == indexPath.row {
if limit < 100{
limit += 10
callAPI()
}
while callAPI function is:
func callAPI () {
PostService.getPosts(limit: limit) { (postsArray, error) in
if error == nil {
guard let postsArray = postsArray else {return}
self.postsArray = postsArray
DispatchQueue.main.async {
self.postsCollectionView.reloadData()
}
}
}
}
}
Of course, you will change the naming dependent on your project.
Hope it helps

Related

Paginating the movie DB in swift

im having trouble setting up pagination in swift with the MovieDB API
normally you would have a limit and an offet then that would relay to your model array .count -1
when working with CollectionViews
Im working with a diffable datasource and cannot see the solution
has anyone manage to implement this or something similar?
current API service looks like this
class APIService {
static let shared = APIService()
//always pass in your first API so the one which holds title, release date ect
func fetchMovies(completionHandler: #escaping ([Movie]?, Error?) -> ()) {
guard let url = URL(string: APINOWPLAYING) else {
print("not a valid url")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let data = data {//when Decoding use the 2nd API model with the array
if let decodedResponse = try? JSONDecoder().decode(Movies.self, from: data) {
DispatchQueue.main.async {
completionHandler(decodedResponse.results, nil)
print("TOTAL RESULTS \(decodedResponse.page)")
}
return
}
}
print("Fatch Failed \(error?.localizedDescription ?? "error unknown")")
}.resume()
}
view controller
private func setupDiffableDataSource() {
collectionView.dataSource = diffDataSource
//MARK:- SetupHeader under Compositional Sections Extension
setupHeader()
APIService.shared.fetchMovies { (movies, err) in
APIService.shared.fetchTopMovies { (movieGroup, err) in
var snapshot = self.diffDataSource.snapshot()
snapshot.appendSections([.topSection])
snapshot.appendItems(movies ?? [], toSection: .topSection)
snapshot.appendSections([.bottomSection])
let objects = movieGroup?.results ?? []
snapshot.appendItems(objects, toSection: .bottomSection)
self.diffDataSource.apply(snapshot)
}
}
}
does anyone know how to work with API for pagination?
this is what the MOVIEDB api call looks like
let APINOWPLAYING =
"https://api.themoviedb.org/3/movie/now_playing?api_key=(APIKEY)&language=en-US&page=1&total_pages=56"
hoping someone can point me in the right direction
thanks
You can use func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) from UICollectionViewDelegate
You need to update your service so it can handle the page parameter
var isCanLoadMore = false
var currentPage = 1
private func fetchData(page: Int) {
// your API request
// remember to change isCanLoadMore = true after apply(snapshot)
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if isCanLoadMore {
if diffableDataSource.snapshot().numberOfSections - 1 == indexPath.section {
let currentSection = diffableDataSource.snapshot().sectionIdentifiers[indexPath.section]
if diffableDataSource.snapshot().numberOfItems(inSection: currentSection) - 1 == indexPath.row {
isCanLoadMore = false
currentPage += 1
print("NEXT PAGE")
fetchData(page: currentPage)
}
}
}
}

How do you properly pass data to a NSObject class for a collection view from Firebase

How do you properly send data to a custom data NSObject class for a collection view? My variables are always returning as nil.
I have a splash screen in it's own view Controller. When all the data I want loaded has finished loading from firebase, I go to the main screen of the app via performSegue(withIdentifier:), here's the code for the code in question from the SplashScreenViewController:
func getDatabaseReference(){
let d = DispatchGroup()
d.enter()
let encodedURL = (postIDRefDic["post1"]! + "/postURL")
ref.child(encodedURL).observe(.value, with: { (snapshot) in
let newUrl = snapshot.value as! String
DemoSource.shared.url = newUrl
d.leave()
})
d.notify(queue: .main){
self.performSegue(withIdentifier: "showHome", sender: nil)
}
}
in the above code you can see that I'm seguing to my next view controller, HomeViewController, in the HomeViewController class I have a collection view which is helped by a custom class (the NSObject class) called DemoSource (also show above) that I'm using to assign the new data I just got in a variable within that class. This DemoSource class is a custom data class of type NSObject:
import UIKit
import Firebase
struct DataObj {
var image: UIImage?
var play_Url: URL?
var title = ""
var content = ""
}
class DemoSource: NSObject {
static let shared = DemoSource()
var demoData = [DataObj]()
var url = ""
override init() {
demoData += [
DataObj(image: #imageLiteral(resourceName: "ss-1") , play_Url: URL(string: url), title: "title ", content: "Description")
]
}
}
I use this class with my HomeViewController with the collection view:
import UIKit
import AVKit
import Firebase
import MMPlayerView
class HomeViewController: UIViewController {
var offsetObservation: NSKeyValueObservation?
lazy var mmPlayerLayer: MMPlayerLayer = {
let l = MMPlayerLayer()
l.cacheType = .memory(count: 5)
l.coverFitType = .fitToPlayerView
l.videoGravity = AVLayerVideoGravity.resizeAspect
l.replace(cover: CoverA.instantiateFromNib())
l.repeatWhenEnd = true
return l
}()
#IBOutlet weak var playerCollect: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// remove previous download fails file
MMPlayerDownloader.cleanTmpFile()
self.navigationController?.mmPlayerTransition.push.pass(setting: { (_) in
})
offsetObservation = playerCollect.observe(\.contentOffset, options: [.new]) { [weak self] (_, value) in
guard let self = self, self.presentedViewController == nil else {return}
NSObject.cancelPreviousPerformRequests(withTarget: self)
self.perform(#selector(self.startLoading), with: nil, afterDelay: 0.2)
}
playerCollect.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 200, right:0)
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
self?.updateByContentOffset()
self?.startLoading()
}
mmPlayerLayer.getStatusBlock { [weak self] (status) in
switch status {
case .failed(let err):
let alert = UIAlertController(title: "err", message: err.description, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self?.present(alert, animated: true, completion: nil)
case .ready:
print("Ready to Play")
case .playing:
print("Playing")
case .pause:
print("Pause")
case .end:
print("End")
default: break
}
}
mmPlayerLayer.getOrientationChange { (status) in
print("Player OrientationChange \(status)")
}
}
deinit {
offsetObservation?.invalidate()
offsetObservation = nil
print("ViewController deinit")
}
#IBAction func profileButtonTap(_ sender: Any) {
let uid = (Auth.auth().currentUser?.uid)!
let Splash = SpalshScreenViewController()
Splash.GetProfilePicture(uid: uid)
Splash.GetUsername(uid: uid)
Splash.GetName(uid: uid)
Splash.GetClipsNumber(uid: uid)
Splash.GetFollowersNumber(uid: uid)
Splash.GetFollowingsNumber(uid: uid)
performSegue(withIdentifier: "showProfile", sender: nil)
}
}
extension HomeViewController: MMPlayerFromProtocol {
func backReplaceSuperView(original: UIView?) -> UIView? {
guard let path = self.findCurrentPath(),
let cell = self.findCurrentCell(path: path) as? PlayerCell else {
return original
}
return cell.imgView
}
// add layer to temp view and pass to another controller
var passPlayer: MMPlayerLayer {
return self.mmPlayerLayer
}
func transitionWillStart() {
}
// show cell.image
func transitionCompleted() {
self.updateByContentOffset()
self.startLoading()
}
}
extension HomeViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let m = min(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height)
return CGSize(width: m, height: m*0.75)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
DispatchQueue.main.async { [unowned self] in
if self.presentedViewController != nil || self.mmPlayerLayer.isShrink == true {
//self.playerCollect.scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
//self.updateDetail(at: indexPath)
} else {
self.presentDetail(at: indexPath)
}
}
}
fileprivate func updateByContentOffset() {
if mmPlayerLayer.isShrink {
return
}
if let path = findCurrentPath(),
self.presentedViewController == nil {
self.updateCell(at: path)
//Demo SubTitle
if path.row == 0, self.mmPlayerLayer.subtitleSetting.subtitleType == nil {
}
}
}
}
fileprivate func presentDetail(at indexPath: IndexPath) {
self.updateCell(at: indexPath)
mmPlayerLayer.resume()
if let vc = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController {
vc.data = DemoSource.shared.demoData[indexPath.row]
self.present(vc, animated: true, completion: nil)
}
}
fileprivate func updateCell(at indexPath: IndexPath) {
if let cell = playerCollect.cellForItem(at: indexPath) as? PlayerCell, let playURL = cell.data?.play_Url {
// this thumb use when transition start and your video dosent start
mmPlayerLayer.thumbImageView.image = cell.imgView.image
// set video where to play
mmPlayerLayer.playView = cell.imgView
mmPlayerLayer.set(url: playURL)
}
}
#objc fileprivate func startLoading() {
self.updateByContentOffset()
if self.presentedViewController != nil {
return
}
// start loading video
mmPlayerLayer.resume()
}
private func findCurrentPath() -> IndexPath? {
let p = CGPoint(x: playerCollect.contentOffset.x + playerCollect.frame.width/2, y: playerCollect.frame.height/2)
return playerCollect.indexPathForItem(at: p)
}
private func findCurrentCell(path: IndexPath) -> UICollectionViewCell? {
return playerCollect?.cellForItem(at: path)
}
}
extension HomeViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return DemoSource.shared.demoData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PlayerCell", for: indexPath) as? PlayerCell {
cell.data = DemoSource.shared.demoData[indexPath.row]
return cell
}
return UICollectionViewCell()
}
}
the first time I instantiate the Demosource class is:
extension HomeViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return DemoSource.shared.demoData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PlayerCell", for: indexPath) as? PlayerCell {
cell.data = DemoSource.shared.demoData[indexPath.row]
return cell
}
return UICollectionViewCell()
}
}
When I run my app it crashes as apparently, the url in the data class is nil, even though I set it with the url in my splashscreenviewcontroller? This DemoSource class get's instantiated before the variable is even populated it seems, when I did some debugging with breakpoints.
So my question is, after all this explaining... why isn't the url variable in the DemoSource class still nil and why is the class getting executed before when the view that uses this class is only called AFTER the data has been fetched from Firebase?
You have implemented DemoSource as a singleton, which means that it gets instantiated the first time that you reference DemoSource.shared. This is in getDatabaseReference. When it is instantiated url has its initial value (""), so that is what gets added to the the demoData array.
You don't need an initialiser.
You do need a function to add data to the demoData array.
class DemoSource: NSObject {
static let shared = DemoSource()
var demoData = [DataObj]()
add(urlString: String) {
demoData.append(DataObj(image: #imageLiteral(resourceName: "ss-1") , play_Url: URL(string: urlString), title: "title ", content: "Description"))
}
}
Then, in your getDatabaseReference -
func getDatabaseReference(){
let d = DispatchGroup()
d.enter()
let encodedURL = (postIDRefDic["post1"]! + "/postURL")
ref.child(encodedURL).observe(.value, with: { (snapshot) in
if let newUrl = snapshot.value as? String {
DemoSource.shared.add(urlString: newUrl)
}
d.leave()
})
d.notify(queue: .main){
self.performSegue(withIdentifier: "showHome", sender: nil)
}
}

TableView moves down when fetching data

When I scroll almost to the end of the current table view, it loads more data, and the problem is after reloadData() it almost instantly moves to another cell. For example, if I stopped scrolling on the 12th cell, tableView moves to the 15th. The same with 22 and 25 etc. I don't want my tableView to jump over cells. How can I repair it?
How I check whether its time to load more data:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "previewCell") as! postsCell
let photosForFirstPost = photoURLs[indexPath.row + 1]
//print(photoURLs[0])
if photosForFirstPost?.count != 0 && photosForFirstPost != nil {
let url = photosForFirstPost![0]
// cell.imagePreview.kf.setImage(with: url)
let resource = ImageResource(downloadURL: photosForFirstPost![0], cacheKey: String(describing: photosForFirstPost![0]))
// print(ImageCache.default.isImageCached(forKey: String(describing: photosForFirstPost![0])))
cell.imagePreview.kf.setImage(with: resource)
} else {
cell.imagePreview.image = UIImage(named: "harry")
}
cell.separatorLine.backgroundColor = .blue
cell.themeName.text = "Theme name"
cell.readTime.text = "3 mins read"
cell.textPreview.text = realPosts[indexPath.row].text
if postsTableView.indexPathsForVisibleRows?.first?.row == realPosts.count - 3 {
var arrayOfIndexes = [IndexPath]()
for i in 0...9 {
arrayOfIndexes.append(IndexPath(row: realPosts.count + i, section: 0))
}
requestTenPosts(indexPath: arrayOfIndexes)
}
return cell
}
How I request data at the launch:
func requestForPosts() {
guard let requestURL = URL(string: "https://api.vk.com/method/wall.get?owner_id=\(groupId)&count=\(howMuchPosts)&access_token=\(serviceKey)&v=\(versionOfMethod)&offset=\(offset)") else { return }
do {
self.posts = [try Welcome(fromURL: requestURL)]
realPosts = self.posts[0].response.items
searchPhotos(arrayOfItems: self.realPosts)
offset += howMuchPosts
} catch {
print(error)
}
}
How I request for more data:
func requestTenPosts(indexPath: [IndexPath]) {
guard let requestURL = URL(string: "https://api.vk.com/method/wall.get?owner_id=\(groupId)&count=\(10)&access_token=\(serviceKey)&v=\(versionOfMethod)&offset=\(offset)") else { return }
DispatchQueue.global().async {
do {
self.offset += 10
for howMuchKeysToADD in (self.offset...self.offset + 10) {
self.textOfAPost.updateValue("", forKey: howMuchKeysToADD)
self.photoURLs.updateValue([], forKey: howMuchKeysToADD)
}
var forAMoment = try Welcome(fromURL: requestURL)
var arrayForAMoment: [Item] = []
for i in 0...9 {
self.realPosts.append(forAMoment.response.items[i])
arrayForAMoment.append(forAMoment.response.items[i])
}
print(arrayForAMoment)
print("searchPhotos is called")
self.searchPhotos(arrayOfItems: arrayForAMoment)
DispatchQueue.main.async {
self.postsTableView.reloadData()
}
} catch {
print(error)
}
if postsTableView.indexPathsForVisibleRows?.first?.row == realPosts.count - 3 {
var arrayOfIndexes = [IndexPath]()
for i in 0...9 {
arrayOfIndexes.append(IndexPath(row: realPosts.count + i, section: 0))
}
requestTenPosts(indexPath: arrayOfIndexes)
}else{return}
or use simple else{} and don't forgot to give cell.tag = [indexpath.row]
Instead of reloading the data, can you try inserting the rows at the bottom. Since you already have access to all the index paths, it should not be difficult and table view should not move.
DispatchQueue.main.async {
//self.postsTableView.reloadData()
self.postsTableView.beginUpdates()
self.postsTableView.insertRows(at: indexPath, with: .left)
self.postsTableView.endUpdates()
}

Collection View Cell Duplicates every time I press this button (Swift)

Every time I tap on the like button (heart icon) the cell gets updated just fine but it gets duplicate too. I researched and tried to figure it out on my own but I couldn't see why it's being duplicated.
I investigated and I found that probably this might be a problem with the cellForRowAtIndexPath function but that function looks good to me.
Here's the relevant code:
HomeController.swift:
class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout, HomePostCellDelegate {
let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.register(HomePostCell.self, forCellWithReuseIdentifier: cellId)
let refreshControll = UIRefreshControl()
refreshControll.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
if #available(iOS 10.0, *) {
collectionView?.refreshControl = refreshControll
} else {
// Fallback on earlier versions
}
setupNavigationItems()
fetchAllPost()
}
#objc func handleUpdateFeed() {
handleRefresh()
}
#objc func handleRefresh() {
posts.removeAll()
fetchAllPost()
}
fileprivate func fetchAllPost() {
fetchPosts()
fetchFollowingUserIds()
}
fileprivate func fetchFollowingUserIds() {
guard let uid = FIRAuth.auth()?.currentUser?.uid else { return }
FIRDatabase.database().reference().child("following").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
guard let userIdsDictionary = snapshot.value as? [String: Any] else { return }
userIdsDictionary.forEach({ (key, value) in
FIRDatabase.fetchUserWithUid(uid: key, completion: { (user) in
self.fetchPostsWithUser(user: user)
})
})
}) { (err) in
print("failed to fetch following users ids:", err)
}
}
var posts = [Post]()
fileprivate func fetchPosts() {
guard let currentUserID = FIRAuth.auth()?.currentUser?.uid else { return }
FIRDatabase.fetchUserWithUid(uid: currentUserID) { (user) in
self.fetchPostsWithUser(user: user)
}
}
fileprivate func fetchPostsWithUser(user: User) {
let ref = FIRDatabase.database().reference().child("posts/\(user.uid)/")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if #available(iOS 10.0, *) {
self.collectionView?.refreshControl?.endRefreshing()
} else {
// Fallback on earlier versions
}
guard let dictionaries = snapshot.value as? [String: Any] else { return }
dictionaries.forEach({ (key,value) in
guard let dictionary = value as? [String: Any] else { return }
var post = Post(user: user, dictionary: dictionary)
post.id = key
guard let uid = FIRAuth.auth()?.currentUser?.uid else { return }
FIRDatabase.database().reference().child("likes").child(key).child(uid).observe(.value, with: { (snapshot) in
if let value = snapshot.value as? Int, value == 1 {
post.hasLiked = true
} else {
post.hasLiked = false
}
self.posts.append(post)
self.posts.sort(by: { (p1, p2) -> Bool in
return p1.creationDate.compare(p2.creationDate) == .orderedDescending
})
self.collectionView?.reloadData()
print("fetch post with user reload data")
}, withCancel: { (err) in
print("Failed to fetch info for post")
})
})
}) { (error) in
print("Failed to fetch posts", error)
}
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return posts.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height: CGFloat = 310 // username + userProfileImageView
return CGSize(width: view.frame.width - 27.5, height: height)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! HomePostCell
cell.post = posts[indexPath.item]
cell.delegate = self
cell.photoImageView.image = nil
// Makes cell corners round
cell.layer.masksToBounds = true
cell.layer.cornerRadius = 17
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 20
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 5
}
func didLike(for cell: HomePostCell) {
guard let indexPath = collectionView?.indexPath(for: cell) else { return }
var post = self.posts[indexPath.item]
guard let postId = post.id else { return }
guard let uid = FIRAuth.auth()?.currentUser?.uid else { return }
let values = [uid : post.hasLiked == true ? 0 : 1]
FIRDatabase.database().reference().child("likes").child(postId).updateChildValues(values) { (err, _) in
if let err = err {
print("Failed to like post", err)
return
}
print("Successfully liked post!")
post.hasLiked = !post.hasLiked
self.posts[indexPath.item] = post
self.collectionView?.reloadItems(at: [indexPath])
}
}
}
Let me know if you have any questions, Thank you!

How does pagination work in collectionview?

I am trying to implement a pagination in a demo app. I am using a UICollectionView to display a lot of images from an API using SDWebImage. And the API supports pagination like this:
My problem is how to show this nextPage's images to my collectionview?
{
"meta":{
"code":200
},
"data":{ },
"pagination":{
"total":86,
"totalPages":3,
"page":1,
"nextPage":2,
"nextPageUrl":"http://.............?page=2"
}
}
And my aim is that to show this nextPageUrl's pic to the collectionview.
and here is my code :
class StoreViewController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegate {
#IBOutlet var MyStoreCollectionView: UICollectionView!
var alldata: [PopulerMagazalarData]?
var indexPath: IndexPath?
var storeData : [PopulerMagazalarData] = []
let pagenumber = 1
override func viewDidLoad() {
super.viewDidLoad()
if let indexPath = self.indexPath, let storeData = self.alldata?[indexPath.row] {
let storeusername = storeData.username
GetDataFromUrl(from: "https://............./\(storeusername!)?page=\(pagenumber)")
}
}
And my data get fun from url ...
func GetDataFromUrl(from:String){
Alamofire.request(from, method: .get).validate().responseJSON { response in
switch response.result {
case .success(let value):
let json = JSON(value)
self.storeData = [PopulerMagazalarData]()
//...Creating Data Obj.
let data = PopulerMagazalarData()
let username = json["data"]["store"]["user"]["username"].string
let userpic = json["data"]["store"]["user"]["profilePicture"].string
let productsCount = json["data"]["store"]["productsCount"].int
let description = json["data"]["store"]["description"].string
let followedby = json["data"]["store"]["user"]["counts"]["followedBy"].int
let count:Int? = json["data"]["products"].array?.count
if let ct = count {
for index in 0...ct-1{
let images = json["data"]["products"][index]["images"]["standart"]["url"].string
data.img1 = images
self.storeData.append(data)
}
}
//*****************
data.username = username
data.profilPic = userpic
data.producsCount = productsCount
data.desc = description
data.followedby = followedby
//******************
self.storeData.append(data)
// for refresh collecitonView
self.refresh_now()
case .failure(let error):
print(error)
}
}
}
//...CollectionView ReloadData func...
func refresh_now(){
DispatchQueue.main.async (
execute:
{
self.MyStoreCollectionView.reloadData()
}
)
}
and this is my collectionview funds :
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return 1
}
Please check my this answer first, add a footer view to your collectionview when footerview appears make a network call, append new array to previous array and reload your collectionview
Try this easy solution with help of CCBottomRefreshControl You need to just treat it like simple UIRefreshController.
let bottomRefreshController = UIRefreshControl()
bottomRefreshController.triggerVerticalOffset = 50
bottomRefreshController.addTarget(self, action: #selector(ViewController.refreshBottom), forControlEvents: .ValueChanged)
collectionView.bottomRefreshControl = bottomRefreshController
func refreshBottom() {
//api call for loading more data
loadMoreData()
}

Resources