1

I am trying to create a feature where if a user likes a post, closes the app and reloads the app, the like button is still red and the user will not be able to like the post again unless they unlike it first.

A previous post recommended me to use an array, so thats exactly what I did. I've created an array that when a post is liked, the users UID goes to the array. Array is in "Posts/(postid)"

Now, what I can't figure out is how to see if a users UID is equal to a UID found in this array. My goal is if a users UID is already on the array, set the variable "isLiked" to true. If it's not, have "isLiked" be false (which is already done).

PostViewModel.swift

func addLike(id: String){
        ref.collection("Posts").document(id).updateData(["likes": FieldValue.increment(Int64(1))]) { (err) in
            if err != nil{
                print(err!.localizedDescription)
                return
            }
            self.ref.collection("Posts").document(id).updateData([
                "likedBy": FieldValue.arrayUnion([self.uid])
            ])
        }
    }
    
func unLike(id: String){
    ref.collection("Posts").document(id).updateData(["likes": FieldValue.increment(Int64(-1))]) { (err) in
        if err != nil{
            print(err!.localizedDescription)
            return
        }
        self.ref.collection("Posts").document(id).updateData([
            "likedBy": FieldValue.arrayRemove([self.uid])
        ])
    }
}

PostRow.swift

@State private var isLiked = false

HStack {
    Button(action: {if isLiked == false{
        postData.addLike(id: post.id)
        isLiked = true
    } else{
        postData.unLike(id: post.id)
        isLiked = false
    }}, label: {
        Image(systemName: isLiked ? "heart.fill" : "heart")
            .resizable()
            .aspectRatio(contentMode: .fill)
            .frame(width: 20)
            .foregroundColor(isLiked ? .red : .gray)
    })
}

1 Answer 1

1

It is quite hard to understand what you are doing based on the little code you provided. It looks like you are not using the MVVM as structure. Considering that there are a lot of things I would recommend you do different. Nonetheless what I could extract from your code the following change should do the trick:

HStack {
    Button(action: {if isLiked == false{
        postData.addLike(id: post.id)
        isLiked = true
    } else{
        postData.unLike(id: post.id)
        isLiked = false
    }}, label: {
        Image(systemName: isLiked ? "heart.fill" : "heart")
            .resizable()
            .aspectRatio(contentMode: .fill)
            .frame(width: 20)
            .foregroundColor(isLiked ? .red : .gray)
    }).onAppear(perform: self.isLiked = self.model.checkForLikes(id: post.id)) // update State 
}


class PostViewModel {
    // func addLike
        
    // func unLike
    
    func checkForLikes(id: String) -> Bool { // Add this method
        let doc = ref.collection("Posts").document(id)
        
        return doc.whereField("likedBy", arrayContains: self.uid)
    }
    
}

Here is more information on how to query in Firebase: Firebase Queries

Sign up to request clarification or add additional context in comments.

4 Comments

Also I'd recommend the easy to use Real Time Updates. For this quite some rework would be needed of what I can see in your code but it would mean that you could implement visual updates live without the need of "closes the app and reloads the app"
Sorry, I should have provided my code. Yes, my project is set up as MVVM. Ill take a look at this code in a little bit and let you know if I have any problems. Thank you!
Alright well, adding ".document(id)" to the end of the let doc was incorrect. That is not allowed apparently. Once I removed that, I keep getting the error "Cannot convert value of 'Query' to expected condition type 'Bool'".
Could you please provide all the code necessary? It makes it difficult with just some structures and functions as the one willing to answer your question then has to spend extra time to get all needed parameters etc. See Minimal reproducible example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.