1

I have a function to fetch posts from my Firebase database and populate a collection view, 15 posts at a time using:

ref.child("posts").queryOrderedByKey().queryLimited(toLast: 15).observeSingleEvent(of: .value, with: { (snap) in

Now I want to have the next 15 posts fetched every time the user reaches the bottom of the screen. In my cellForItem method I'm trying to come up with a check to see if the bottom of the page has been reached, and if so, load the next 15 posts where it left off.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "postCell", for: indexPath) as! PostCell

    cell.postImage.loadImageUsingCacheWithUrlString(posts[indexPath.row].pathToImage)
    cell.postID = posts[indexPath.row].postID
    cell.postImage.contentMode = UIViewContentMode.scaleAspectFill

    if indexPath.row == posts.count - 1
    {
        fetchPosts()
    }

    return cell
}

I just don't know how I can specify that when the next 15 posts are loaded, they need to start where the last 15 left off, and not just fetch all the posts in the database again.

This is the whole fetchPosts() function:

func fetchPosts() {

    let ref = FIRDatabase.database().reference()
    ref.child("users").queryOrderedByKey().observe(.value, with: { snapshot in

        let users = snapshot.value as! [String : AnyObject]

        for (_, value) in users {

            if let uid = value["uid"] as? String {

                if uid == FIRAuth.auth()?.currentUser?.uid {

                    if let followingUsers = value["following"] as? [String : String] {

                        for (_, user) in followingUsers {
                            self.following.append(user)
                        }
                    }
                    self.following.append(FIRAuth.auth()!.currentUser!.uid)

                    ref.child("posts").queryOrderedByKey().queryLimited(toLast: 15).observeSingleEvent(of: .value, with: { (snap) in

                        for postSnapshot in snap.children.allObjects as! [FIRDataSnapshot] {
                            let value = postSnapshot.value as! [String : AnyObject]

                            if let userID = value["userID"] as? String {
                                for each in self.following {
                                    if each == userID {

                                        let posst = Post()
                                        if let poster = value["poster"] as? String, let likes = value["likes"] as? Int, let pathToImage = value["pathToImage"] as? String, let postID = value["postID"] as? String {

                                            posst.poster = poster
                                            posst.likes = likes
                                            posst.pathToImage = pathToImage
                                            posst.postID = postID
                                            posst.userID = userID
                                            if let people = value["peopleWhoLike"] as? [String : AnyObject] {
                                                for (_, person) in people {
                                                    posst.peopleWhoLike.append(person as! String)
                                                }
                                            }
                                            posts.append(posst)
                                        }
                                    }
                                }
                                self.collectionView.reloadData()
                            }
                        }
                    })
                    ref.removeAllObservers()
                }
            }
        }
    })
}

What can I add/change here to ensure that 15 posts are loaded, in order, each time the bottom of the page is reached?

KingTim
  • 1,281
  • 4
  • 21
  • 29
  • [This post](http://stackoverflow.com/questions/37430881/swift-ios-firebase-paging/37451950#37451950 ) answers the question. – Jen Person Mar 21 '17 at 22:09

1 Answers1

0

Haven't tried but here is the idea. I would set two variables:

let readLimit:Int = 15
var readOffset:Int = 15

First variable is hardcoded and represents limit, where new results should be loaded.

In cellForItem function, check:

// Check if user scrolled to last row
if (indexPath.item + 1) == readOffset {
  // Yes, scrolled to last row
  // Increase limit to load more from database
  readOffset += readLimit

  // Call function which loads data from database
  self.fetchPosts()
} 

Do you see where am I getting? Now you have to modify read function a bit: Change queryLimited(toLast: 15): replace 15 with self.readOffset

Keep in mind that this has not been tested, just wrote it here to help you understand.

ZassX
  • 1,369
  • 2
  • 14
  • 35
  • Trying this, is looks like it doesn't follow the readLimit of 15 because upon loading the app, the collection view populates infinitely, with lots of duplicates. – KingTim Mar 20 '17 at 17:32