Veronika Babii
Veronika Babii

Reputation: 384

Save array in Firestore and display it in the uitableview in Swift

I'm using Swift and Firestore, where I have collection of tasks.

I populate each tableview cell with a task data. There is a field hashtags. Now it's just a string, but I want it to be an array of strings.
How can I save array of strings in Task model and correctly display it in the tableview?

My Task model file:

import Foundation
import FirebaseFirestore

protocol DocumentSerializable {
    init?(dictionary:[String:Any])
}

struct Task {
    var title: String
    var description: String
    var tip: String
    var hashtags: String

    var dictionary:[String:Any] {
        return [
            "title": title,
            "description": description,
            "tip": tip,
            "hashtags": hashtags
        ]
    }
}

extension Task : DocumentSerializable {

    init?(dictionary: [String : Any]) {

            let title = dictionary["title"] as? String ?? "Error! Title Field Not Found!"
            let description = dictionary["description"] as? String ?? "Error! Description Field Not Found!"
            let tip = dictionary["tip"] as? String ?? "Error! Tip Field Not Found!"
            let hashtags = dictionary["hashtags"] as? String ?? "Error! Hashtags Field Not Found!"

        self.init(title: title, description: description, tip: tip, hashtags: hashtags)
    }
}

My TableViewViewController file:

    import UIKit
    import Firebase
    import FirebaseAuth
    import FirebaseFirestore

    class TasksListScreen: UIViewController {

        var db = Firestore.firestore()
        var tasksArray = [Task]()

        @IBOutlet weak var tableView: UITableView!

        override func viewDidLoad() {
            super.viewDidLoad()
            loadData()
    }

    // load data from the user tasks collection to the table view
    func loadData() {

        let userID = Auth.auth().currentUser!.uid
        let userTasksCollRef = db.collection("users").document(userID).collection("tasks")

        userTasksCollRef.getDocuments { (queryShapshot, error) in
            if let error = error {
                print("Error loading data: \(error.localizedDescription)")
            } else {
                self.tasksArray = queryShapshot!.documents.compactMap({Task(dictionary: $0.data())})

                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            }
        }
    }
}

extension TasksListScreen: UITableViewDataSource, UITableViewDelegate {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tasksArray.count
    }

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

        let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell") as! TaskViewCell

        let task = tasksArray[indexPath.row]

        cell.previewTitleLabel.text = task.title
        cell.previewMotivLabel.text = task.description
        cell.previewTipLabel.text = task.tip
        cell.previewHashtagsLabel.text = task.hashtags

        cell.cellDelegate = self
        cell.index = indexPath

        return cell
    }
    }

Upvotes: 0

Views: 356

Answers (1)

Frankenstein
Frankenstein

Reputation: 16341

Firstly, You should modify the hashtags property in Task and the init?(dictionary:) method. Like this:

struct Task {
    var title: String
    var description: String
    var tip: String
    var hashtags: [String]

    var dictionary:[String: Any] {
        return [
            "title": title,
            "description": description,
            "tip": tip,
            "hashtags": hashtags
        ]
    }
}

extension Task: DocumentSerializable {

    init?(dictionary: [String : Any]) {

            let title = dictionary["title"] as? String ?? "Error! Title Field Not Found!"
            let description = dictionary["description"] as? String ?? "Error! Description Field Not Found!"
            let tip = dictionary["tip"] as? String ?? "Error! Tip Field Not Found!"
            let hashtags = dictionary["hashtags"] as? [String] ?? ["Error! Hashtags Field Not Found!"]

        self.init(title: title, description: description, tip: tip, hashtags: hashtags)
    }
}

Then you need to modify the cellForRow method's following line to pass the array and display it properly.

Modify this:

cell.previewHashtagsLabel.text = task.hashtags

To:

cell.handleHashTags(task.hashtags)

You need to add a new method in TaskViewCell class named handleHashTags and handle the array of strings [String] passed to display them.

Upvotes: 1

Related Questions