0

What I have right now: A page that displays all like that a user has received. If someone keeps hitting the like button, each like will be displayed on this page. That is too much. I want to make it so that even if someone hits the like button continuously, only one of those likes will be displayed. In other words what I need is a way to limit the likes displayed (of made) to 1 per day or session.

I have been going back and forth trying to decide whether to make the limit when the like is pressed or when the like is displayed (on different pages for different users obviously).

Here is some code for the page of the user who sees all the likes of him/herself.

func printPersonInfo(uid: String) {
print(uid)
 let usersRef = Database.database().reference().child("people")
 let thisUser = usersRef.child(uid)
 thisUser.observeSingleEvent(of: .value, with: { snapshot in
 let photoPosts = snapshot.childSnapshot(forPath: "PhotoPosts").value as? String ?? "No PhotoPosts"
 let education = snapshot.childSnapshot(forPath: "Education").value as? String ?? "No Education"
  let whatIamConsideringBuying = snapshot.childSnapshot(forPath: "WhatIamConsideringBuying").value as? String ?? "No WhatIamConsideringBuying"
 print(photoPosts, education, whatIamConsideringBuying)
 let p = Usery(education: education, whatIamConsideringBuying: whatIamConsideringBuying, photoPosts: photoPosts)
 self.person.insert(p, at: 0)
 self.table.reloadData()

Here's some more downstream

 public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell

    let immy = cell.viewWithTag(2) as! UIImageView

    let person1: Usery = person[indexPath.row]


    cell.lblName1.text = person1.education
    cell.lblgenre1.text = person1.whatIamConsideringBuying

    if let photoPosts = person1.photoPosts {
        let url = URL(string: photoPosts)
        immy.sd_setImage(with: url)
    }

    return cell

}

This is the database structure:

 "peeps" : {
    "5VbL3Adj7teM2KNJkF4GIexBJhE2" : {
      "Education" : "Yale",
      "PhotoPosts" :     "https://firebasestorage.googleapis.com/v0/b/daylike-2f938.appspot.com/o/images%2FPhotoPosts?alt=media&token=42d76567-ac42-4728-9914-1d7c2fa4d5e6",
      "WhatIamConsideringBuying" : "Twitter: Carla9",
      "caption1" : {
        "caption1" : 1570097725719,
        "keyToPost" : "-LqG6V0RVEyFNt9Zu9CE"
      },
      "likes" : 565,
      "peopleWhoLike" : {
        "-LmLjHwwGj1kt5qLM20X" : "NMNQYJ5z64fATK2MMs7m0ggHl0k2",
        "-LmLtlp5Sm900SV8xP4i" : "NMNQYJ5z64fATK2MMs7m0ggHl0k2",

The page where the like is made contains a Pressed function for when like is pressed.

(UPDATE after answer)

   let ref = Database.database().reference()
    let keyToPost = ref.child("likes").childByAutoId().key

    ref.child("people").child(self.postID).observeSingleEvent(of: .value, with:  {(snapshot) in

        if let people = snapshot.value as? [String: AnyObject] {
            let updateLikes: [String: Any] = ["peopleWhoLike/\(keyToPost)" : Auth.auth().currentUser!.uid]

            ref.child("people").child(self.postID).updateChildValues(updateLikes, withCompletionBlock: { (error, reff) in



                if error == nil {
                    ref.child("people").child(self.postID).observeSingleEvent(of: .value, with: { (snap) in
                        if let properties = snap.value as?[String: AnyObject]{
                            if let likes = properties["peopleWhoLike"] as? [String : AnyObject] {
                                let count = likes.count
                            let update = ["likes" : count]
                                ref.child("people").child(self.postID).updateChildValues(update)

additional code

  let uid = Auth.auth().currentUser!.uid
    print("H", uid)
        let thisUserRef = Database.database().reference().child("people").child(uid)
        let myPeopleRef = thisUserRef.child("peopleWhoLike")
   myPeopleRef.observeSingleEvent(of: .value, with: { snapshot in
            let peopleArray = snapshot.children.allObjects as! [DataSnapshot]
            for person in peopleArray {
                let personUid = person.value as! String

                self.printPersonInfo(uid: personUid)
            }
        })
  • Could you not check if they have liked it with an `if` and then only let the like pass through if they have not? – AlexH Oct 10 '19 at 22:50
  • @AlexH good idea but the the next time/day it would not allow a like – SeattleSurfer Oct 12 '19 at 09:26
  • Do you track when they like? – AlexH Oct 13 '19 at 00:34
  • @AlexH That should work. I just made a snapshot for that. My problem now is reading it to make the if statement because it is tied to the user who liked it and isn't just a simple child shot. If you're interested, I asked it in another question here https://stackoverflow.com/questions/58384696/how-can-a-timestamp-nestled-in-a-firebase-double-or-string-be-retrieved-via-sn If you add your comment as answer here, I'll mark it as the solution. – SeattleSurfer Oct 15 '19 at 19:53
  • I added it as an answer – AlexH Oct 15 '19 at 20:02
  • Is the answer enough or should I add some more? @SeattleSurfer – AlexH Oct 15 '19 at 20:12

2 Answers2

2

If you want to have this type of limit on Firebase (and many other NoSQL databases too), consider modeling it into your data.

In your current model you use push IDs for each new vote.

"peopleWhoLike" : {
  "-LmLjHwwGj1kt5qLM20X" : "NMNQYJ5z64fATK2MMs7m0ggHl0k2",
  "-LmLtlp5Sm900SV8xP4i" : "NMNQYJ5z64fATK2MMs7m0ggHl0k2"
}

Since each time you call push/childByAutoId() is guaranteed to generate a unique new location, users can generate upvotes as often as they want.


If you only want each user to be able to vote once, you could for example store the data like this:

"peopleWhoLike" : {
  "NMNQYJ5z64fATK2MMs7m0ggHl0k2": true,
  "another-Uid-ThatIs-Different": true
}

Now if the same person tries to vote again, they're just setting the same data to true again, so nothing changes.

The true in the above is meaningless (you just can't store a key without a value), but you could also use it to keep track of how often the user has clicked the like button:

"peopleWhoLike" : {
  "NMNQYJ5z64fATK2MMs7m0ggHl0k2": 3,
  "another-Uid-ThatIs-Different": 2
}

This way you can determine how many people liked the post (by counting the number of nodes), but also how many times they liked it (by summing the values).


If you want to allow the user to like something once per time-interval, you can model that into your data model too:

"peopleWhoLike" : {
  "20191010": {
    "NMNQYJ5z64fATK2MMs7m0ggHl0k2": true
  },
  "20191010": {
    "NMNQYJ5z64fATK2MMs7m0ggHl0k2": true,
    "another-Uid-ThatIs-Different": true
  }
}

To write a structure of this type, you could use something like:

ref.child("people")
   .child(self.postID)
   .child("peopleWhoLike")
   .child("20191012")
   .child(Auth.auth().currentUser!.uid)
   .setValue(true)
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Very good answer. The former is quite interesting, but I'd have to go for the latter. How would you get the date to form part of the "NMNQYJ5z64fATK2MMs7m0ggHl0k2": true"? – SeattleSurfer Oct 11 '19 at 22:06
  • https://stackoverflow.com/questions/35700281/date-format-in-swift? – Frank van Puffelen Oct 11 '19 at 22:43
  • Thanks, what I kind of mean is how can you get that into the database with the other elements of the database there? I realize I should have added that part of the code too, and will now put it in the question. Also, in route number 2, is there a reason you have to exclude the auto id? – SeattleSurfer Oct 11 '19 at 23:26
  • I added a sample of how to write the data in the last snippet of my answer. – Frank van Puffelen Oct 12 '19 at 14:05
  • is there nay way to incorporate it in the structure I am already using when like is pressed? I use that structure in other pages and code segments, so I'd like to not deviate if possible. – SeattleSurfer Oct 12 '19 at 22:41
  • the problem I believe lies in that previous that part of the code was string, now we have a dictionary and bool. I get error elsewhere Could not cast value of type '__NSDictionaryM' (0x7fff87a8bb20) to 'NSString' (0x7fff87b450e8). I'll add that part to the question – SeattleSurfer Oct 12 '19 at 23:19
0

To do this, track when the user likes the post. If the user has not liked the post today, then they may continue. If not, display a message telling them that they may not like the post.

In pseudo-code:

if (user has liked post && the like is today) {
display message
} else {
allow the like to go through
}
AlexH
  • 828
  • 7
  • 26