1
votes

I'm fairly new with firebase so my lack of code isn't a lack of trying more of a just "I dont really know where to begin here".

I'm trying to only show posts that are 10 minutes "old" or less. I'm going to run a timer in my app to send the query every second (assuming this doesn't cause too much of an issue?) to check to make sure the current posts aren't over that 10 minute mark, and if they are, the query just shouldn't return them.

I've got it set up where when the user makes a post a timestamp is created.

The setup is :

Posts 
   02983094jfksdflkaj3l
      timestamp: 23478923019

I'm assuming I need to orderByValue? to sort the posts by the timestamp and then return it with a limit of some sort, but I'm not sure how to map all of that out.

A point in the right direction would be greatly appreciated here.

Thanks in advance!

edit: I'm no longer getting any posts appearing in the collectionview...and no matter how many posts I have that should satisfy the under 10 minute query, only one ever returns.

Like I show below, I'm not getting a .value return on the snap...which should return the timestamp value I get shown in the timestamp snap print, no?

 override func viewWillAppear(animated: Bool) {
    let cutoff = UInt64(1000 * floor(NSDate().timeIntervalSince1970) - 10*60*1000);
    let cutoffFloat = Float(cutoff) // <-- woudnlt take a UInt64 as an AnyObject. I assume its ok to just do this?


    DataService.ds.REF_POSTS.queryOrderedByChild("timestamp").queryStartingAtValue(cutoffFloat).observeSingleEventOfType(.ChildAdded) { (snapshot: FIRDataSnapshot) in
        print("child added") // <------- isn't ever getting called
        self.Posts = []
      if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {

            for snap in snapshots {

             print("timestamp snap: \(snap)") // <---- returns timestamp snap: Snap (timestamp) 23904819242

                      if let postDict = snap.value as? Dictionary<String, AnyObject> {

                    print(snap.value)// <----- Returns nothing
                    let key = snap.key
                    let post = Post(postKey: key, dictionary: postDict)
                    self.Posts.append(post)

                }
            }
        }

        self.collectionView.reloadData()

}

I don't know if it's any help but here was my code I was using before to populate the collection view:

   DataService.ds.REF_POSTS.observeEventType(.Value) { (snapshot: FIRDataSnapshot) in

        self.Posts = []
        if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {

            for snap in snapshots {

                print(snap)

                if let postDict = snap.value as? Dictionary<String, AnyObject> {
                    let key = snap.key
                    let post = Post(postKey: key, dictionary: postDict)
                    self.Posts.append(post)
                }
            }
        }

       print("got here")
       self.collectionView.reloadData()


    }
2
The timer is probably unnecessary, and you may want to consider a situation where, in the last 10 minutes, there were 1024 posts. How many of those posts should be delivered to your client(s)? My guess is that while you may be interested in all of them you really only want to view 20 at a time (for example) or maybe just the most recent 20. And remember Firebase as asynchronous - by adding an observer to a node your app will automatically be notified of new posts - so it will always have the latest posts displayed. Polling can often be eliminated completely by letting Firebase do the work. - Jay
@Jay 9 posts will only ever be allowed to be shown to a user at a time from a group of friends, and the 10 minute bit is important to a feature I'm trying to implement. It's okay if there are no posts showing as the point of the app is to interact with a post that has a limited amount of "show time". If I'm just pulling from a user's friend's posts with a limit of 9 there shouldn't be an issue with a flood of information or anything ye? I'm also just assuming that this is the best way to go about this. Do you see anything glaringly wrong with going about it this way? - Barkley

2 Answers

3
votes

Running a timer and sending a different query every 10 seconds is a horrible use of a realtime database. Instead run the query once asking for all posts since 10 minutes ago and keep that query active.

Borrowing from @JustinM's code:

let ref = FIRDatabase.database().reference
let cutoff = UInt64(1000 * floor(NSDate().timeIntervalSince1970) - 10*60*1000);    
ref.child("post")
   .queryOrderedByChild("timestamp")
   .queryStartingAtValue(cutoff)
   .observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in
       let post = Post(title: snapshot["title"], timestamp: snapshot["timestamp"])
       self.postsArray.append(post)
   }

   self.tableView.reloadData()

    // start a timer that removes expired items from postsArray
    NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "removeExpiredItems", userInfo: nil, repeats: true)
})

Then client-side run your timer and discard the posts as they "expire".

func removeExpiredItems() {
    let cutoff = UInt64(1000 * floor(NSDate().timeIntervalSince1970) - 10*60*1000)
    while (self.postsArray.count > 0 && self.postsArray[0].timestamp < cutoff) {
        // remove first item, because it expired
        self.postsArray.removeAtIndex(0)
    }
    self.tableView.reloadData()
}
2
votes

Here is how you would set a running timer:

NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector "updateTime", userInfo: nil, repeats: true)

}
func updateTime() {
     let currentTime = NSDate()
    self.time = currentTime.description

}

Then to query firebase for posts from last ten minutes:

let ref = FIRDatabase.database().reference
//let x = currentTime - 10 minutes in equivalent time structure. For example, if by minutes, currentTime - 10. You put that in queryStartingAtValue.
ref.child("post").queryOrderedByChild("timestamp").queryStartingAtValue("x").observeSingleEventOfType(.Value, withBlock: { snapshot in
        self.postsArray.removeAll
        for snap in snapshot.children {
            let post = Post(title: snap["title"], timeStamp: snap["timestamp"])
            self.postsArray.append(post)
        }

      self.tableView.reloadData()
    })

queryStartingAtValue will give you all posts that have the value you assign or greater.

There are some better ways to handle this that are a little more involved but this should be a good start, the New Firebase has some great docs and examples. Check out their section on Database/retrieve data for more on sorting/filtering.

Hope this helps you get started, let me know if you have any questions.