Reputation: 76
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
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