heyylateef
heyylateef

Reputation: 76

Can't view dictionary data from Firebase

I had a working solution before, but I couldn't find a way to delete an entry on Firebase. The old solution only deleted entries on the local device(only the "list" and "desc" arrays would delete from the local device, but not the database). So I added the "post" variable to keep each title and description tied together with a unique ID, so I may retrieve that ID to delete the entry from the database.

Now using the "post" variable, the title and description uploads to Firebase but I'm having trouble retrieving and displaying data that I posted on firebase on my UITableView. I get an error when I try to append snapshot data into my dictionary named "post".

An error occurs at this line:

        if let itemArray = snapshot.value as? [[String : Optional <String>]]
        {
            post.append(itemArray) \\ERROR: Value of type '[String : Optional<String>]' has no member 'append'
            self.myTableView.reloadData()
        }

    }

Here is the full code below

class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {

//******THIS IS THE TABLEVIEWCONTROLLER******
@IBOutlet weak var myTableView: UITableView!    // link to tableview item in storyboard

//required function when using tableview; wants to know how many cells to produce (takes template from prototype cell in storyboard)
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    return(list.count)
}

// required function when using tableview; actual link to each cell from storyboard
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
    let cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "cell")
    cell.textLabel?.text = list[indexPath.row]
    return (cell)
}

//function allows you to swipe left to delete an entry(cell)
public func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath){
    if editingStyle == UITableViewCell.EditingStyle.delete
    {
        var key = [String]()
        ref?.child(key[indexPath.row]).setValue(nil)    // removes a entry on Firebase using its unique ID
        key.remove(at: indexPath.row)
        list.remove(at: indexPath.row)
        desc.remove(at: indexPath.row)
        myTableView.reloadData()
    }
}
 override func viewDidAppear(_ animated: Bool) {//change "viewDidLoad()" back to "viewDidAppear()"
    ref = Database.database().reference()                  // sets the variable "ref" to connect to our Firebase database

    list.removeAll()    // Deletes all older data, so only data thats on the Firebase Database will be added to the "list" array
    desc.removeAll()    // Deletes all older data, so only data thats on the Firebase Database will be added to the "desc" array


    let alert = UIAlertController(title: "Enter Details for Your Post", message: "", preferredStyle: UIAlertController.Style.alert)
    let titleField = alert.textFields![0] as UITextField
    let descField = alert.textFields![1] as UITextField
    let key = ref?.child("task").childByAutoId().key
    let post = ["uid": key,                             // Gets auto generated ID for database entry
        "title": titleField.text,                    // Saves the title field to Firebase
        "description": descField.text]         // Saves the description field to Firebase
    handle = ref?.child("task").observe(.childAdded, with: { (snapshot) in    // looks for each title in the tasks'title directory in the Firebase database, so it may display them on the tableview
        if let itemArray = snapshot.value as? [[String : Optional <String>]]
        {
            post.append(itemArray)
            self.myTableView.reloadData()
        }

    }

)}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    myIndex = indexPath.row
    performSegue(withIdentifier: "detailsegue", sender: self)
}


@IBAction func quickAdd(_ sender: UIButton) // Link to add button on FirstViewController
{
    uploadToFirebase(title: "Post the task?", message: "Enter a title and description for your task")
}

func uploadToFirebase (title: String, message: String)
{
    let alert = UIAlertController(title: "Enter Details for Your Post", message: "", preferredStyle: UIAlertController.Style.alert)

    alert.addTextField(configurationHandler: { (titleField : UITextField!) in       // Adds a textfield to the alert
        titleField.placeholder = "Enter item"
    })
    alert.addTextField(configurationHandler: { (descField : UITextField!) in        // Adds a textfield to the alert
        descField.placeholder = "Enter Description"
    })

    let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.default, handler: {   // Adds cancel button to alert; voids whatever has been inputted
        (action : UIAlertAction!) -> Void in })
    let saveAction = UIAlertAction(title: "Save", style: UIAlertAction.Style.default, handler: { (action : UIAlertAction! )  in // Adds save button to alert; saves the tasks to Firebase if clicked
        let titleField = alert.textFields![0] as UITextField
        let descField = alert.textFields![1] as UITextField
        if (titleField.text != "")              // Checks to make sure titleField isn't empty
        {
            if (descField.text != "")           // Checks to make sure descField isn't empty
            {
                let key = ref?.child("task").childByAutoId().key
                let post = ["uid": key,                             // Gets auto generated ID for database entry
                    "title": titleField.text,                    // Saves the title field to Firebase
                    "description": descField.text]         // Saves the description field to Firebase
                ref?.child("task").child(key!).setValue(post)      // Saves the task for Firebase, ties each post with a unique ID
            }
        }
    })
    alert.addAction(saveAction)
    alert.addAction(cancelAction)
    self.present(alert, animated: true, completion: nil)        // Presents the alert on screen
 }
}

Here is my Firebase Database. The data under the child "task" doesn't appear on the UITableView

{
"task" : {
"-LT4Xtdo7Z0oyqHXHgif" : {
  "description" : "4:02 desc",
  "title" : "4:02 test",
  "uid" : "-LT4Xtdo7Z0oyqHXHgif"
},
"-LU6eMyaKN9DZF-YYiLU" : {
  "description" : "You Know!",
  "title" : "HU",
  "uid" : "-LU6eMyaKN9DZF-YYiLU"
},

Upvotes: 0

Views: 271

Answers (1)

Yogesh Tandel
Yogesh Tandel

Reputation: 1754

Create your model File in below format

class ListModel: NSObject {
    var UID:String?
    var Title:String?
    var Description:String?
}

In Your ViewController

var Obj : ListModel?
var ListArr = [ListModel]()




let ref = Database.database().reference().child("tasks")
        ref.observe(.childAdded, with: { (snapshot) in
            print(snapshot)
            guard let dictionary = snapshot.value as? [String : AnyObject] 
else {
                return
            }

            let Obj = ListModel()
            Obj.UID = snapshot.key
            Obj.Title= dictionary["title"] as? String
            Obj.Description = dictionary["description"] as? String

            self.ListArr.append(Obj)

           //ReloadTable Here

           tableView.reloadData()


}, withCancel: nil)

Upvotes: 0

Related Questions