Search code examples
swiftaws-amplify

How to populate UICollectionView with array of data?


I have a UICollectionView that I populate with data from an AWS Amplify List Query function. The array of data from the function successfully prints out to the console but it only returns 1 cell with elements from one authuserPost and the corresponding the fields. I have set the struct UserPostData to equal the elements inside of the posts array. My problem is that my for loop only gets data for one post and only showing one cell when there should be 5 total cells. However when I print(element) it shows all 5 post with their own elements. Can anyone point me into the right direction as to what I am doing wrong?

Here is my code:

import UIKit
import Amplify
import AmplifyPlugins
import AWSMobileClient

struct UserPostData {
    var id: String?
    var userSub: String?
    var zipcode: String?
    var contactMethod: String?
    
}

class UserPostsViewController: UIViewController {
    
    var userSubID = String()
    var numberOfPosts = Int(0)
    var data = [UserPostData]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        fetchData()
        setupUI()
    }
    
    lazy var collectionView: UICollectionView = {
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewLayout())
        collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
        collectionView.backgroundColor = .tertiarySystemBackground
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()
    
    func fetchData(){
        userSubID = AWSMobileClient.default().userSub!
        let post = authuserPost.keys
        let predicate = post.userSub == userSubID
        _ = Amplify.API.query(request: .list(authuserPost.self, where: predicate)) { event in
            switch event {
            case .success(let result):
                switch result {
                case .success(let posts):
                    DispatchQueue.main.async {
                        self.numberOfPosts = posts.count
                        self.collectionView.reloadData()
                        
                        for element in posts{
                            self.data = [UserPostData.init(id: element.id, userSub: element.userSub, zipcode: element.zipcode, contactMethod: element.contactMethod)]
                            print(element) //When I print element it shows all post and their elements. The Output will be at the bottom of the question.
                            
                        }
                        
                        //print("Successfully retrieved list of posts: \(posts)")
                    }
                case .failure(let error):
                    print("Got failed result with \(error.errorDescription)")
                }
            case .failure(let error):
                print("Got failed event with error \(error)")
            }
        }
        
    }
    
}

// MARK: - UICollectionViewDelegate & Data Source
extension UserPostsViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return data.count // It only returns one cell
        
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
        cell.dogImageView.image = UIImage(named: "image1")
        cell.zipcodeLabel.text = data[indexPath.section].zipcode
        cell.contactMethod.text = data[indexPath.section].contactMethod
        cell.layoutSubviews()
        return cell
    }
    
}

When I print(element) inside of the for loop i get this to the console.

authuserPost(id: "0600D60E-2270-4B1A-AE8C-7E42F2B32F9C", userSub: "47bcd9ba-78f9-4d2f-9685-8a97b3a69e77", zipcode: "30316", contactMethod: "(444)085-5666")
authuserPost(id: "6FDD8A2D-D6A6-4CDC-AD05-5D5E085178DD", userSub: "47bcd9ba-78f9-4d2f-9685-8a97b3a69e77",  zipcode: "30308", contactMethod: "(444)869-6665")
authuserPost(id: "58A3431C-7AAE-4AB0-B89E-87D932C09017", userSub: "47bcd9ba-78f9-4d2f-9685-8a97b3a69e77", zipcode: "30316", contactMethod: "(444)869-4534")
authuserPost(id: "C9DF31BE-6FC0-410C-90EE-24E13617199F", userSub: "47bcd9ba-78f9-4d2f-9685-8a97b3a69e77", zipcode: "30316", contactMethod: "(444)869-4534")
authuserPost(id: "5BD76C91-7D3A-424B-99F7-6330EE0AD6AF", userSub: "47bcd9ba-78f9-4d2f-9685-8a97b3a69e77", zipcode: "30316", contactMethod: "(444)869-3453")

Solution

  • When you loop through the posts array and assign [UserPostData.init(...)] to it, you are actually reassigning the self.data property over and over again. Only the last one will survive.

    So instead of assigning to the array, you should append UserPostData for each post in the iteration.


    You should replace

    self.data = [UserPostData.init(id: element.id, userSub: element.userSub, zipcode: element.zipcode, contactMethod: element.contactMethod)]
    

    with

    self.data.append(UserPostData.init(id: element.id, userSub: element.userSub, zipcode: element.zipcode, contactMethod: element.contactMethod))