How to refresh a view?

Hi,


I’ve been trying to refresh a view to reload its data,

for example, let’s say the user has a name called Bill,

if im going to another view to change his name to Jack,

when Im going back to the previous view to see his name changed,

it’s still Bill, only if I’m running the app again it’s showing the changed result- Jack.


Is there a way to refresh the view every time I’m going back to that view?

NewsViewController is actually the parent, because it's instantiating to the PostCommentController


it reloads the first view (NewsViewController) and been updated.

but if i'm on NewsViewController and I'm like\unlike, it doesnt update the PostCommentController immediately,

only when I'm presenting it for the second time.


So, how do you want to update the child, which is not loaded ?


To do so, you need to pass the new value in prepare for segue, and use it to set up the IBOutlets in child view (VC2: PostCommentController) . Or do it on the instance of child view immediately after instanciated.

What's happening is that:

If i'm on NewsViewController and i'm pressing like\unlike button-

it's changing the value for UserDefaults(code below for like\unlike buttons)

If I'm going to PostCommentController, which is instantiating to, with the current post cell's data,

I'm recieving the value that changed in UserDefaults(code below) for cellForItemAt in collectionView,

I set the same way in PostCommentController for like\unlike buttons and cellForItemAt(I add a collectionView for the post

in CommentPostController) so it's changing the values in UserDefaults.

If I'm dismissing the view, and go back to NewsViewController, it's changing for each cell in the collectionView its buttons,

like I did set in PostCommentController- so if I did unlike, all of the buttons in each cell in NewsViewController's collectionView is 'unlike'.

How do I change the values for the specific post cell?


@IBActionfunc likePressed(_ sender: Any) {
        self.likeBtn.isEnabled = false
        let ref = Database.database().reference()
        let keyToPost = ref.child("posts").childByAutoId().key
       
        ref.child("posts").child(self.postID).observeSingleEvent(of: .value, with: { (snapshot) in
            if let post = snapshot.value as? [String : AnyObject]{
               
                let  updateLikes: [String : Any] = ["peopleWhoLike/\(keyToPost!)" : Auth.auth().currentUser!.uid]
                ref.child("posts").child(self.postID).updateChildValues(updateLikes, withCompletionBlock: { (error, reff) in
                    if error == nil{
                        ref.child("posts").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
                                    self.likeLabel.text = "\(count) Likes"
                                    let update = ["likes" : count]
                                    ref.child("posts").child(self.postID).updateChildValues(update)
                                   
                                    self.likeBtn.isHidden = true
                                    self.unlikeBtn.isHidden = false
                                    self.likeBtn.isEnabled = true
                                   
                                    let defaults = UserDefaults.standard
                                    let likeButton = "likeButton"
                                    let unlikeButton = "unlikeButton"
                                    let likesTextLabel = "likesTextLabel"
                                    defaults.set(self.likeBtn.isHidden, forKey: likeButton)
                                    defaults.set(self.unlikeBtn.isHidden, forKey: unlikeButton)
                                    defaults.set(count, forKey: likesTextLabel)
                                }
                            }
                        })
                    }else{
                        print(post)
                    }
                })
            }
        })
        ref.removeAllObservers()
    }


@IBActionfunc unlikePressed(_ sender: Any) {
        self.unlikeBtn.isEnabled = false
        let ref = Database.database().reference()
        ref.child("posts").child(self.postID).observeSingleEvent(of: .value, with: { (snapshot) in
            if let properties = snapshot.value as? [String : AnyObject]{
                if let peopleWhoLike = properties["peopleWhoLike"] as? [String : AnyObject]{
                    for (id,person) in peopleWhoLike{
                        if person as? String == Auth.auth().currentUser!.uid{
                            ref.child("posts").child(self.postID).child("peopleWhoLike").child(id).removeValue(completionBlock: { (error, reff) in
                                if error == nil{
                                    ref.child("posts").child(self.postID).observeSingleEvent(of: .value, with: { (snap) in
                                        if let prop = snap.value as? [String : AnyObject]{
                                            if let likes = prop["peopleWhoLike"] as? [String : AnyObject]{
                                                let count = likes.count
                                                self.likeLabel.text = "\(count) Likes"
                                                ref.child("posts").child(self.postID).updateChildValues(["likes" : count])
                                                let defaults = UserDefaults.standard
                                                let likesTextLabel = "likesTextLabel"
                                                defaults.set(count, forKey: likesTextLabel)
                                            }else{
                                                self.likeLabel.text = "0 Likes"
                                                ref.child("posts").child(self.postID).updateChildValues(["likes" : 0])
                                                let defaults = UserDefaults.standard
                                                let likesTextLabel = "likesTextLabel"
                                                defaults.set(0, forKey: likesTextLabel)
                                            }
                                        }
                                    })
                                }
                            })
                            self.likeBtn.isHidden = false
                            self.unlikeBtn.isHidden = true
                            self.unlikeBtn.isEnabled = true
                           
                            let defaults = UserDefaults.standard
                            let likeButton = "likeButton"
                            let unlikeButton = "unlikeButton"
                           
                            defaults.set(self.likeBtn.isHidden, forKey: likeButton)
                            defaults.set(self.unlikeBtn.isHidden, forKey: unlikeButton)
                           
                            break
                        }
                    }
                }
            }

        })
        ref.removeAllObservers()
    }
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "postCell", for: indexPath) as! PostCell
       
        let inverseIndex = self.posts.count - indexPath.row - 1
       
        cell.postImage.downloadImage(from: self.posts[inverseIndex].pathToImage)
        cell.authorLabel.text = self.posts[inverseIndex].author
        cell.likeLabel.text = "\(self.posts[inverseIndex].likes!) Likes"
        cell.postID = self.posts[inverseIndex].postID
        cell.authorImage.downloadImage(from: self.posts[inverseIndex].authorImage)
       
        let string = self.posts[inverseIndex].timeAgo
        let df = DateFormatter()
        df.dateFormat = "yyyy/MM/dd, H:mm:ss"
        let result = df.date(from: string!)
       
        let timeDate = timeAgoSinceDate(result!)
            cell.timeLabel.text = timeDate
       
        cell.commentBtn.addTarget(self, action: #selector(buttonClicked(sender:)), for: .touchUpInside)
      
        let defaults = UserDefaults.standard
        let likeButton = "likeButton"
        let unlikeButton = "unlikeButton"
        let likesTextLabel = "likesTextLabel"
       
        if let likeBttn = defaults.value(forKey: likeButton){
            cell.likeBtn.isHidden = likeBttn as! Bool
        }
        if let unlikeBttn = defaults.value(forKey: unlikeButton){
            cell.unlikeBtn.isHidden = unlikeBttn as! Bool
        }
        if let likesLabel = defaults.value(forKey: likesTextLabel){
            cell.likeLabel.text = "\(likesLabel) Likes"
        }
       
        for person in self.posts[inverseIndex].peopleWhoLike{
            if person == Auth.auth().currentUser!.uid{
                cell.unlikeBtn.isHidden = false
                cell.likeBtn.isHidden = true
              
                break
            }
       
        }

Sorry for the trivial questions.


Have you checked yo execute lines 24 to 30 ?


I do not understand immediately why code is so different for like and unlike.


collectionView is in PostCommentController, right ?

In cellForItemAt, you call, regardless of indexPath.row:

        if let likeBttn = defaults.value(forKey: likeButton){
            cell.likeBtn.isHidden = likeBttn as! Bool
        }

So, like and unlike is the same for all items in Collection. Is it what you want ?

It's different for like and unlike because in like button, it's setting the amount of likes, if it has 0 likes or more, your'e adding to the amount.

In unlike button you have a seperate code for counting- if you unlike it and no one else like it- 0 likes,

otherwise it's the amount -1 likes.


collectionView is in PostCommentController and in NewViewController as well.

I want like and unlike buttons to be just for the current post in PostCommentController, a specific one(postID), not for all of them.

And every post(cell) in NewsViewController with his own like and unlike buttons.

I want like and unlike buttons to be just for the current post in PostCommentController, a specific one(postID), not for all of them.


func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "postCell", for: indexPath) as! PostCell 
        
        let inverseIndex = self.posts.count - indexPath.row - 1 
        
        cell.postImage.downloadImage(from: self.posts[inverseIndex].pathToImage) 
        cell.authorLabel.text = self.posts[inverseIndex].author 
        cell.likeLabel.text = "\(self.posts[inverseIndex].likes!) Likes" 
        cell.postID = self.posts[inverseIndex].postID 
        cell.authorImage.downloadImage(from: self.posts[inverseIndex].authorImage) 
        
        let string = self.posts[inverseIndex].timeAgo 
        let df = DateFormatter() 
        df.dateFormat = "yyyy/MM/dd, H:mm:ss" 
        let result = df.date(from: string!) 
        
        let timeDate = timeAgoSinceDate(result!) 
            cell.timeLabel.text = timeDate 
        
        cell.commentBtn.addTarget(self, action: #selector(buttonClicked(sender:)), for: .touchUpInside) 
       
        let defaults = UserDefaults.standard 
        let likeButton = "likeButton" 
        let unlikeButton = "unlikeButton" 
        let likesTextLabel = "likesTextLabel" 
        
        if let likeBttn = defaults.value(forKey: likeButton){ 
            cell.likeBtn.isHidden = likeBttn as! Bool 
        } 
        if let unlikeBttn = defaults.value(forKey: unlikeButton){ 
            cell.unlikeBtn.isHidden = unlikeBttn as! Bool 
        } 
        if let likesLabel = defaults.value(forKey: likesTextLabel){ 
            cell.likeLabel.text = "\(likesLabel) Likes" 
        } 
        
        for person in self.posts[inverseIndex].peopleWhoLike{ 
            if person == Auth.auth().currentUser!.uid{ 
                cell.unlikeBtn.isHidden = false 
                cell.likeBtn.isHidden = true 
               
                break 
            } 
        
        }

Line 28 and 31, you set the isHidden depending on the defaults.value you have stored before.

That is the same value for all cells in collection.

For instance, all like are hidden and all unlike are visible


Lines 39 & 40, you look for all people who liked and if it is the currentUser you show only like button.

But if all like are hidden and all unlike are visible, that will change nothing.


So, I don't understand what you are doing there. Do I miss something ?

That's right. so how do I change it to be just for the indexPath.row instead for all of the buttons?

You're right, it's doing nothing if I change the value of the buttons, it's just for when you're rerunning the app,

it resets the buttons according to it.


Can I store each indexPath.row's buttons values?

let's say if I change the buttons in post no.1, it won't change every other post's buttons,

so in other collectionViews, this indexPath.row ID save the buttons change but won't affect other posts.

I need a clearer picture to answer.


for this, I need to step back a little. Please confirm question after question


In Collection View:

Is it correct that you have either like or unlike visible, exclusive: you cannot have bot hidden nor both visible ?

But then, what is the like count in collection view ?

normally you show the number of likes and number of unlike, so both can be visible ? Exact ?

What is self.posts[inverseIndex].peopleWhoLike ? It is an array of people who like ?


If i'm on NewsViewController and i'm pressing like\unlike button-

When you are there, this in fact the detailed corresponding to a single cell of collection view that is displayed ?

This is the post of the author of the post ?

You have only one like / unlike button ?


it's changing the value for UserDefaults(code below for like\unlike buttons)

If you do it this way, without keeping track of which post you are editing, thet will be useless in collection view.

So, what you could do, instead of storing a single bool, would be to store an array of Bool, dimensioned as the size of the collectionView.

But if you need to count likes and count unlike, you should store arrays of Int to keep the count ;

or may be you have to save posts[for the right index]].peopleWhoLike


If I'm going to PostCommentController, which is instantiating to, with the current post cell's data,

I'm recieving the value that changed in UserDefaults(code below) for cellForItemAt in collectionView,

I set the same way in PostCommentController for like\unlike buttons and cellForItemAt(I add a collectionView for the post

in CommentPostController) so it's changing the values in UserDefaults.

If I'm dismissing the view, and go back to NewsViewController, it's changing for each cell in the collectionView its buttons,

like I did set in PostCommentController- so if I did unlike, all of the buttons in each cell in NewsViewController's collectionView is 'unlike'.

How do I change the values for the specific post cell?

Answer will depend on answers above, hence they are really important.

If you have saved arrays (either of Bool or Int), that is what you will have to use to set cell.likeBtn.isHidden with the right index of UserDefaults



Depending also on answers, the best could be to use delegate instead of UserDefaults ; but we should look at this later, once you made it work with UserDefaults.

Claude31 - I so admire your willingness to dive into the depth of these problems. You are to be commended. I cannot do the same. My approach is just to point out possible directions that the OP can explore and can, perhaps, learn from that exploration. It is so much easier for me than for you - I even have refused to learn Swift! Somewhere in Swift heaven you will be rewarded.


OP - The idea is to record in the Model the value of the relevant variables, not just the current relevant variable. In this case you want to record the value of each "button" - or actually what each button represents - its on/off value and perhaps also name and even its color. You do that by having a mutable array of values, or better, an array of mutable dictionaries. Then for each indexPath you select from that array the correct value for that button.

Claude31, just to let you know, I really appreciate your hard work to help me,

It's just so frustrating with those buttons.


In Collection View:

Is it correct that you have either like or unlike visible, exclusive: you cannot have bot hidden nor both visible ?

That's correct.

But then, what is the like count in collection view ?

Like count- if let's say there are 3 users, all 3 of them liked the post, so there's an amount of 3, if one of them unliked the post, now you have an amount of 2.

normally you show the number of likes and number of unlike, so both can be visible ? Exact ?

The answer above. The number is for both of the buttons, if the user liked the post- it add +1,

if the user unliked the post it reduces the amount by 1.

If the post has 0 likes, no user can unlike the post,

all of them has just the option of like button. Both cannot be visible.

What is self.posts[inverseIndex].peopleWhoLike ? It is an array of people who like ?

An array of users who like the post, so if there are 3 users- the amount is 3.


When you are there, this in fact the detailed corresponding to a single cell of collection view that is displayed ?

Yes, each single cell separately in collection view.

This is the post of the author of the post ?

Yes, the post\s of the author(other user\s) and the current user's post\s.

You have only one like / unlike button ?

In each cell I have one like\unlike button, if you press like- it's hiding like and showing unlike button,

if you press unlike- it's hiding unlike button and showing like button.


I will try to store an array of Bool and Int(dimensioned as the size of the collectionView) like you mentioned.

If you have an example for that, that will be very helpful.

I will let you know how it goes.


Thank you!

You may need to be a little careful. When you retrieve an array from an NSUserDefault it is always an array, not a mutableArray. So you may need to make a mutable copy of that array each time you want to change it.

>Claude31, just to let you know, I really appreciate your hard work to help me


And yet, the only 'liked' comment in this neverending 40 post tutorial so far, wasn't from him... Where's that xmas spirit 😉


Ken

How to refresh a view?
 
 
Q