Jeremy Lim
Jeremy Lim

Reputation: 43

How to make sequential firebase query in swift?

Below is my data structure:

{    
    "posts": {

        "xyz1": {
          "author": "Jan",
          "uid": "abc123",
        },
        "xyz2": {
          "author": "Jenny",
          "uid": "abc456",
        },

      }

    "users": {
        "abc123": {
          "email": "[email protected]",
          "profilePicURL": "https://firebasestorage.googleapis.com/v0/b/",
        },
        "abc456": {
          "email": "[email protected]",
          "profilePicURL": "https://firebasestorage.googleapis.com/v0/c/",
        },
      }    
}

I want to display the list of "posts" entries in a tableview.

 let postRef = ref.child("posts")

        postRef.observe(.childAdded, with: { (snapshot) in
            let authorText = snapshot.value!.object(forKey: "author") as! String
            let userIDText = snapshot.value!.object(forKey: "uid") as! String
            }) { (error) in
                print(error.localizedDescription)
            }

How can i use the "uid" retrieved from the above query to make a sequential query to retrieve the "profilePicURL" using the "uid" value in the "users". End goal is to display profilePic stored besides the post in the tableview.

Thank you for any help rendered.

Upvotes: 1

Views: 233

Answers (2)

Jeremy Lim
Jeremy Lim

Reputation: 43

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


    let cell = tableView.dequeueReusableCell(withIdentifier: "HomeCell", for: indexPath) as! HomeTableViewCell

    cell.author.text = String(self.author[(indexPath as NSIndexPath).row])    
    let userIDText = String(self.userID[(indexPath as NSIndexPath).row])

    ref.child("users").child(userIDText).observeSingleEvent(of: .value, with: { (snapshot) in
        print("snaphot is \(snapshot)")
        let imageLink = snapshot.value?["profileImageUrl"] as! String
        self.storageRef = FIRStorage.storage().reference(forURL: imageLink)

        cell.profilePic.loadImageUsingCacheWithUrlString(urlString: imageLink)

    }) { (error) in
        print(error.localizedDescription)
    }
    return cell      
}

I use the following extension for UIImageView to load the image using the URL and it worked!!

 let imageCache = NSCache<AnyObject, AnyObject>()

        extension UIImageView {

            func loadImageUsingCacheWithUrlString(urlString: String) {

            self.image = nil

            //check cache for image first
            if let cachedImage = imageCache.object(forKey: urlString) as? UIImage {
                self.image = cachedImage
                return
            }

            //otherwise fire off a new download
            let url = NSURL(string: urlString)
            URLSession.shared.dataTask(with: url! as URL, completionHandler: { (data, response, error) in

                //download hit an error so lets return out
                if error != nil {
                    print(error)
                    return
                }

                DispatchQueue.main.async(execute: {

                    if let downloadedImage = UIImage(data: data!) {
                        imageCache.setObject(downloadedImage, forKey: urlString)

                        self.image = downloadedImage
                    }
                })

            }).resume()
        }

    }

Upvotes: 1

David Seek
David Seek

Reputation: 17132

Best idea is to store different Users into an Array of Users in which User is a Struct.

struct User {
   var name: String = ""
   var id: String = ""
}

Then in your ViewController you download the content from your Firebase and create Models of your User Struct.

let users: [User] = []

yourFireBaseQueryFunc() {
    ...
    postRef.observe(.childAdded, with: { (snapshot) in

         for item in snapshot {

              let name = snapshot.value!.object(forKey: "author") as! String
              let id = snapshot.value!.object(forKey: "uid") as! String
              let user = User(name: name, id: id)
              users.append(user)
         }

Then for example in a tableView you take the indexPath and one Model out of your Model Array and call a function to get the Image Link from your Firebase:

cellForRowAtIndexPath... {
    let user = users[indexPath.row]
    let image = getImage(user.id)
    let imgURL = NSURL(string: post.picture)
    cell.yourImageView.sd_setImageWithURL(imgURL)
}

And then Query for the image:

func getImage(userID: String) -> String {

    var imageLink: String = ""

    let ref = firebase.child("users").child(userID)
    ref.observeEventType(.Value, withBlock: { snapshot in

        if snapshot.exists() {
            imageLink = snapshot.value!.valueForKey("profilePicURL") as! String
        }

    })

    return imageLink
}

Upvotes: 0

Related Questions