Tarvo Mäesepp Tarvo Mäesepp - 19 days ago 4
Swift Question

Updating key value inside JSON if user updates profile image

first of all I want to say, I am asking because if I screw something up then the whole user base is gone!

I am trying to update key value pair in posts when it belongs to the current user if user changes his profile image because I do not know other method to display the most current image if user changes his image after posting.

So I came up with this and I would like to know, is it the right way to do it?

FIRDatabase.database().reference().child("posts")
.queryOrdered(byChild: "username")
.queryEqual(toValue: self.currentUser.generalDetails.userName)
.observeSingleEvent(of: .value, with: { snapshot in

if let snapDict = snapshot.value as? [String:AnyObject] {
for each in snapDict {
FIRDatabase.database().reference().child("posts/\(each.key)")
.updateChildValues(["profileImageUrl" : downloadUrl!.absoluteString])
}
}
})


If the struct is like this:

posts //All posts
-KVfMmYqMny0n0_5gx9t //Post autogenerated key
comments
profileImageUrl: "http://..."
username: "John"

Jay Jay
Answer

In response to a comment made by the OP:

The question is how to keep a users profile image updated with posts they make even if they change their image.

Here's a users node

users
  -YMka9s0okspoaSf
    name: "Kirk"
    profileImageURL: "http://"
  -YJos09m0ao098Ko
    name: "Spock"
    profileImageURL: "http://"

and then a posts node that contains the post and keeps a reference to each user that made the post

posts //All posts
 -KVfMmYqMny0n0_5gx9t //Post autogenerated key
    comment: "Yes, I love Italian, and so do you"
    posted_by: "YMka9s0okspoaSf"
 -KZKoa99jksoopd0a9Hq //Post autogenerated key
    comment: "Yes"
    posted_by: "YJos09m0ao098Ko"

And then finally some overly verbose code that loads the posts and captures the name and image from the reference

let postsRef = ref.child("posts")
let usersRef = ref.child("users")

postsRef.observeSingleEvent(of: .value, with: { snapshot in
    for data in snapshot.children {
            //convert the enumerator to a snapshot
            let snap = data as! FIRDataSnapshot

            //capture the value as a dictionary of String:String key:value pairs
            let dict = snap.value! as! [String:String]

            //grab the uid of the user that made the post
            let uid = dict["posted_by"]!
            let comment = dict["comment"]!

            //craft a reference to the user that made the post
            let thisUserRef = usersRef.child(uid)

            //read in the users name once and print it
            thisUserRef.observeSingleEvent(of: .value, with: { snapshot in
                let dict = snapshot.value as! [String:String]
                let name = dict["name"]! as String
                let imageRef = dict["profileImageURL"]! as String

                //on this line, load the image and display it
                //then print the user and their comment
                print("User \(name) said \(comment))

            })
    }
})

This technique will always keep the users image fresh and tied to their posts if they change it.

You could simplify it and just keep a reference to the users image directly in the posts node as well, but I recommend keeping the uid in the posts node as it's more query-able and provides access to other user data.

This would allow you to, for example, allow the user reading the post to click on the user name to see what their favorite food is.

Comments