1

I built my app to have news feed like Facebook. My problem is that I don't know how to fetch child images in Post and show it in a collectionView. Please show me how to do it. Appreciate any help.

Here is the db structure:

Posts
   d7j3bWMluvZ6VH4tctQ7B63dU4u1:
       20181112101928:
          avatar: "https://platform-lookaside.fbsbx.com/platform/p..."
          content: "Funny image"
          images:
              -LR4vaEIggkGekc-5ZME:
                       "https://firebasestorage.googleapis.com/v0/b/hon..."
              -LR4vaENC-IsePibQYxY:                             
                       "https://firebasestorage.googleapis.com/v0/b/hon..."
          name: "Thành Trung"
          time: 1541992768776.3628
          type: "Funny"

Here is my code:

   func getDataFromPostFirebase() {
        let getPostData = databaseReference.child("Posts")
        getPostData.observe(.childAdded) { (snapshot) in
            getPostData.child(snapshot.key).observe(.childAdded, with: { (snapshot1) in
                getPostData.child(snapshot.key).child(snapshot1.key).observe(.value, with: { (snapshot2) in
                    self.arrayImageUrl = [String]()
                    if let dict = snapshot2.value as? [String : Any] {
                        guard let avatar = dict["avatar"] as? String else {return}
                        guard let content = dict["content"] as? String else {return}
                        guard let name = dict["name"] as? String else {return}
                        guard let time = dict["time"] as? Double else {return}
                        guard let type = dict["type"] as? String else {return}
                        if let images = dict["images"] as? [String : String] {
                            for image in images.values {
                                self.arrayImageUrl.append(image)
                            }
                            let newPost = Post(avatarString: avatar, contentString: content, nameString: name, timeDouble: time, typeString: type)
                            self.arrayPost.append(newPost)
                            DispatchQueue.main.async {
                                self.feedTableView.reloadData()
                            }
                        } else {
                            let newPost = Post(avatarString: avatar, contentString: content, nameString: name, timeDouble: time, typeString: type)
                            self.arrayPost.append(newPost)
                            DispatchQueue.main.async {
                                self.feedTableView.reloadData()
                            }
                        }
                    }
                })
            })
        }
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return arrayImageUrl.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! TrangChu_CollectionViewCell

        cell.imgContent.layer.cornerRadius = CGFloat(8)
        cell.imgContent.clipsToBounds = true
        cell.imgContent.layer.borderWidth = 2
        cell.imgContent.layer.borderColor = #colorLiteral(red: 0.4756349325, green: 0.4756467342, blue: 0.4756404161, alpha: 1)

        let url = URL(string: arrayImageUrl[indexPath.row])
        cell.imgContent.sd_setImage(with: url, completed: nil)

        return cell
    }

Model object

import Foundation

class Post {
    var avatar : String
    var content : String
    var images : [String]?
    var name : String
    var time : Double
    var type : String

    init(avatarString : String, contentString : String, nameString : String, timeDouble : Double, typeString : String) {
        avatar = avatarString
        content = contentString
//        images = imagesString
        name = nameString
        time = timeDouble
        type = typeString
    }
}
2
  • I guess you need to loop your images node as you have multiple data in it. Commented Nov 12, 2018 at 9:02
  • thanks for your comment, i loop it already but the images show wrong in collectionView Commented Nov 12, 2018 at 9:06

3 Answers 3

3

As what I've said your db is not well structured. I suggest you re structure it like this.

Posts
   d7j3bWMluvZ6VH4tctQ7B63dU4u1:
      avatar: "https://platform-lookaside.fbsbx.com/platform/p..."
      content: "Funny image"
      images:
          -LR4vaEIggkGekc-5ZME: "https://firebasestorage.googleapis.com/v0/b/hon..."
          -LR4vaENC-IsePibQYxY: "https://firebasestorage.googleapis.com/v0/b/hon..."
      name: "Thành Trung"
      time: 1541992768776.3628
      type: "Funny"
      timestamp: 1540276959924

I removed the timestamp node and transferred it along the children node. Now you can fetch the posts with this.

ref.child("Posts").observe(.childAdded) { (snapshot) in
        var post = Post()

        let val = snapshot.value as! [String: Any]
        post.name = val["name"] as? String

        self.ref.child("Posts").child(snapshot.key).child("images").observeSingleEvent(of: .value, with: { (snap) in
            post.imagesString = [String]()
            for image in snap.children.allObjects as! [DataSnapshot] {
                post.imagesString?.append(image.value as! String)
                print("images \(image.value)")
            }

            list.append(post)
            print("post \(post)")
        })

If you want to order the posts you can achieve it using queryOrderedByChild("timestamp")

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

10 Comments

i change the db structure already, but images from all post append in array images so each post show all of images from other post. please help me how to fix this
the array for collectionView to show image may be wrong. help me how to fix it please
Please update the code you've done so far. @TrungNguyen
I update already @elbert rivas. I fetch the image success but I think the array of collectionView have wrong data. It only shows images of last post. please have a look
Update your db structure also @TrungNguyen
|
0

Add this to access your images:

guard let images = dict["images"] as? [[String: Any]] { return }
let imagesString: [String] = []
for imageDict in images {
    for key in imageDict.keys {
        if let imageName = imageDict[key] as? String else {
        // here you access your image as you want
            imagesString.append(imageName)
        }
    }   
}

Then when creating the post object you use imagesString that we created:

let newPost = Post(avatarString: avatar, contentString: content, imagesString: imagesString, nameString: name, timeDouble: time, typeString: type)

5 Comments

it doesn't work, show the error "Cannot subscript a value of type '[String : String]' with an index of type 'Dictionary<String, String>.Keys'"
i want to append it to array model Post. So how can i do that. The image already showed in collection view but it duplicate. How can i fix that
What's the issue?
nothing appear on screen. Seem Post array append nothing
0

You can fetch the images values using this

ref.child("Posts").observe(.childAdded) { (snapshot) in

        self.ref.child("Posts").child(snapshot.key).observe(.childAdded, with: { (snapshot1) in
            self.ref.child("Posts").child(snapshot.key).child(snapshot1.key).child("images").observe(.childAdded, with: { (snap) in
                let post = new Post()
                for rest in snap.children.allObjects as! [DataSnapshot] {
                    //append images 
                    post.imagesString.append(rest.value)
                }


                post.avatarString = snapshot1.value["avatar"] as? String
                ...
            })
        })

I suggest you change the structure of your db because its nested. Refer here

5 Comments

how can i fetch image into Post array, and show it to collectionView. Please help me
i will try it now. Thanks bro for your helping
images from all post append in array images so each post show all of images from other post. please help me how to fix this
Check my new answer @TrungNguyen
thanks rivas, i will try it now. thank you so much for your helping

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.