Firebase data not displaying in tableview in xcode - ios

I have been trying to retrieve profile data from firebase realtime database and displaying it in a table view, so far when I run the simulator the tabelview shows up blank and Failed : error 0:50 [50] shows up. I am pretty new to swift and am not sure what the problem is.
Here is my code:
import UIKit
import FirebaseDatabase
import FirebaseStorage
import FirebaseAuth
class userViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return profileData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "firstName_cell",
for: indexPath)
self.tableView.reloadData()
cell.textLabel?.text = self.profileData[indexPath.item]
return cell
}
var profileData = [String]()
let storageRef = Storage.storage().reference()
var databaseRef = Database.database().reference()
var ref: DatabaseReference?
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
//let userID = Auth.auth().currentUser?.uid
ref?.child("users").observeSingleEvent( of: .childAdded, with: { (snapshot) in
let profile = snapshot.value as? String
if let actualProfile = profile{
self.profileData.append(actualProfile)
print(self.profileData)
self.tableView.reloadData()
}
}) { (error) in
print(error.localizedDescription)
}
}
}

Don’t add reloadData() in cellForRow method.... it will become infinite loop .. so remove self.tableView.reloadData() from cellForRow method

You try to reload your tableView while its reloading.
You should not call tableView.reloadData() in tableView(_:cellForRowAt:) method or any other UITableViewDataSource method that is called from same UITableView.

Related

How to get Firestore documents and display them on a UITableView

Screenshot of Firestore Project
I want to display the "first_name" field for each document in the collection (In the UITableView. The UITableView just shows up blank every time I run the app.
CODE:
import UIKit
import Firebase
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var filterButton: UIButton!
#IBOutlet weak var userTableView: UITableView!
var usersArray = [String]()
var db: Firestore!
override func viewDidLoad() {
super.viewDidLoad()
userTableView.delegate = self
userTableView.dataSource = self
// Do any additional setup after loading the view.
db = Firestore.firestore()
loadData()
}
func loadData() {
db.collection("users").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
self.usersArray.append(document.documentID)
}
}
print(self.usersArray)
self.userTableView.reloadData()
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("Tableview setup \(usersArray.count)")
return usersArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = userTableView.dequeueReusableCell(withIdentifier: "userCell", for: indexPath) as! UserCell
let user = usersArray[indexPath.row]
cell.fullNameLabel.text = user
print("Array is populated \(usersArray)")
return cell
}
}
Doesn't look like you registered the cell to the tableView. Try using: tableview.register(UserCell,forCellReuseIdentifier:"Your reuseIdentifier string"). Try inserting this in viewDidLoad.

Data Parsing firebase

I plan to retrieval data from Database Firebase to TableView by this code what is wrong with my code and how can i fix it to let all details send to my table view
Firebase database
Run at Phone
And this is my data in the database:
import UIKit
import Firebase
class Ordersv: UIViewController, UITableViewDataSource, UITableViewDelegate {
var array = [String]()
var ref: DatabaseReference!
var handle: DatabaseHandle!
#IBOutlet weak var TableView: UITableView!
#IBAction func add (_ sender: Any){
if textField.text != ""{
ref.child("list").childByAutoId().setValue(textField.text)
textField.text = ""
}
}
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
handle = ref?.ref.child ("Orders/Customer/Detils/").observe(.value, with: { (snapshot) in
if let item = snapshot.value as? String {
self.array.append(item)
self.TableView.reloadData()
}
})
self.TableView.delegate = self
self.TableView.dataSource = self
// Do any additional setup after loading the view.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = TableView.dequeueReusableCell(withIdentifier: "Cell")! as UITableViewCell
cell.textLabel?.text = array[indexPath.row]
return cell
}
}
There are a few things wrong wit the code:
You never initialize ref.
When you observe .value, you get multiple nodes back. Your code doesn't handle this fact.
To fix both, I recommend:
let ref = Database.database().reference()
handle = ref.child("Orders/Customer/Detils/").observe(.childAdded, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let name = value?["Name"] as? String ?? ""
self.array.append(name)
self.TableView.reloadData()
})
The above code observes the .childAdded event, which fires immediately for each existing child node, and then once for every subsequent child that is added.

FireBase is returning strings as nil

Man, UITableView's just do not want to work with me. I have been outputting strings to Firebase storage and I see the values stored. My problem is that I cannot output any of those strings into the UITableView. I just see a blank table view and when I go and try to see what is being outputted by thoughtObjects.thoughts it just says "nil." If anyone can help figure out what is wrong that would be appreciated. Thank you so much StackOverflow.
import UIKit
import Firebase
import FirebaseDatabase
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var inputThoughtTextField: UITextField!
#IBOutlet weak var successfulUploadLbl: UILabel!
#IBOutlet weak var tableView: UITableView!
var refThoughts: DatabaseReference!
var thoughtList = [ThoughtModel]()
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return thoughtList.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
//creating a cell using the custom class
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! VCTableViewCell
//the artist object
let thoughtObjects: ThoughtModel
//getting the artist of selected position
thoughtObjects = thoughtList[indexPath.row]
//adding values to labels
cell.wordCloud.text = thoughtObjects.thoughts
//print(cell.wordCloud.text)
//returning cell
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
refThoughts = Database.database().reference().child("thoughts");
refThoughts.observe(DataEventType.value, with: { (snapshot) in
//if the reference have some values
if snapshot.childrenCount > 0 {
//clearing the list
self.thoughtList.removeAll()
//iterating through all the values
for thoughts in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
let thoughtsObject = thoughts.value as? [String: AnyObject]
let thoughtText = thoughtsObject?["thoughts"]
let thoughtId = thoughtsObject?["id"]
//creating artist object with model and fetched values
let thoughtCreation = ThoughtModel(id: thoughtId as! String?, thoughts: thoughtText as! String?)
//appending it to list
self.thoughtList.append(thoughtCreation)
}
//reloading the tableview
self.tableView.reloadData()
}
})
}
#IBAction func buttonAddThought(_ sender: UIButton){
addThought()
}
func addThought(){
let key = refThoughts.childByAutoId().key
let thought = ["id": key,
"Thoughts": inputThoughtTextField.text! as String
]
refThoughts.child(key).setValue(thought)
successfulUploadLbl.text = "Thought Uploaded"
}
}

'NSInternalInconsistencyException', reason: 'attempt to insert row 0 into section 0, but there are only 0 sections after the update'

I am making an iOS app but I keep getting this error:
'NSInternalInconsistencyException', reason: 'attempt to insert row 0 into section 0, but there are only 0 sections after the update'
I have researched this question for 2 days now but I don't know what's wrong. I am putting my code down below.
import UIKit
import FirebaseDatabase
import FirebaseAuth
class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var databaseRef = Database.database().reference()
var loggedInUser:AnyObject?
var loggedInUserData:NSDictionary?
#IBOutlet weak var aivLoading: UIActivityIndicatorView!
#IBOutlet weak var homeTableView: UITableView!
var posts = [NSDictionary]()
override func viewDidLoad() {
super.viewDidLoad()
self.loggedInUser = Auth.auth().currentUser
self.databaseRef.child("users").child(self.loggedInUser!.uid).observeSingleEvent(of: .value) { (snapshot: DataSnapshot) in
self.loggedInUserData = snapshot.value as? NSDictionary
self.databaseRef.child("posts").child(self.loggedInUser!.uid).observe(.childAdded, with: { (snapshot: DataSnapshot) in
self.posts.insert(snapshot.value as! NSDictionary, at: 0)
self.homeTableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: UITableViewRowAnimation.automatic)
self.aivLoading.stopAnimating()
}){(error) in
ProgressHUD.showError("There was an error, try again")
}
}
self.homeTableView.rowHeight = UITableViewAutomaticDimension
self.homeTableView.estimatedRowHeight = 140
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: HomeTableViewCell = tableView.dequeueReusableCell(withIdentifier: "HomeTableViewCell", for: indexPath) as! HomeTableViewCell
let post = posts[(self.posts.count-1) - (indexPath.row)]["text"] as! String
cell.configure("Anonymous", post: post)
return cell
}
}
In my code, it refers to a dequeueReusableCell, with the identifier HomeTableViewCell, which is a Swift file. Here is the code for that Swift file:
import UIKit
import FirebaseDatabase
import Firebase
import FirebaseAuth
class HomeTableViewCell: UITableViewCell {
#IBOutlet weak var nameConstant: UILabel!
#IBOutlet weak var post: UITextView!
override open func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
open func configure(_ nameConstant: String, post: String) {
self.post.text = post
self.nameConstant.text = "Anonymous"
}
}
I know there are similar questions to mine but a lot of those are in Objective-C. I've looked at the Swift ones too but they don't help.
If anyone has any ideas to fix this that would be great. Thanks in advance!
In your code you're always returning 1 for number of rows. But i guess you should be returning posts.count right? Every time you insertRows(at:... the table checks consistency through the delegate. There's also something weird, you're appending to your list (self.posts.append(snapshot.value as! NSDictionary)) but then you're inserting row 0-0?, I'll assume you want to insert new post to the top. Moreover if you have just one section, you don't need to implement the method.
So here's the code (I'm assuming the firebase and cell configuration code is correct):
import UIKit
import FirebaseDatabase
import FirebaseAuth
class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var databaseRef = Database.database().reference()
var loggedInUser:AnyObject?
var loggedInUserData:NSDictionary?
#IBOutlet weak var aivLoading: UIActivityIndicatorView!
#IBOutlet weak var homeTableView: UITableView!
var posts = [NSDictionary]()
override func viewDidLoad() {
super.viewDidLoad()
self.loggedInUser = Auth.auth().currentUser
self.databaseRef.child("users").child(self.loggedInUser!.uid).observeSingleEvent(of: .value) { (snapshot: DataSnapshot) in
self.loggedInUserData = snapshot.value as? NSDictionary
self.databaseRef.child("posts").child(self.loggedInUser!.uid).observe(.childAdded, with: { (snapshot: DataSnapshot) in
self.posts.insert(snapshot.value as! NSDictionary, at: 0)
self.homeTableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: UITableViewRowAnimation.automatic)
self.aivLoading.stopAnimating()
}){(error) in
ProgressHUD.showError("There was an error, try again")
}
}
self.homeTableView.rowHeight = UITableViewAutomaticDimension
self.homeTableView.estimatedRowHeight = 140
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: HomeTableViewCell = tableView.dequeueReusableCell(withIdentifier: "HomeTableViewCell", for: indexPath) as! HomeTableViewCell
let post = posts[(self.posts.count-1) - (indexPath.row)]["text"] as! String
cell.configure("Anonymous", post: post)
return cell
}
}
I hope it fixes your problem ;)

How to retrieve a list in Firebase database folder?

I have a folder in my Database called "Cars", within the folder is a list of car brands, I want to retrieve all the brands and put it in a UITableView. Then when you press on a brand it will show the models of the brand. I have a trouble retrieving the list of cars at the moment. This is the screenshot of my Database and my code for the view controller.
import UIKit
import Firebase
import FirebaseDatabase
import SDWebImage
struct carStruct {
let cars : String!
}
class CarMakeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var cars = [carStruct]()
override func viewDidLoad() {
super.viewDidLoad()
let ref = Database.database().reference().child("Cars")
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount)
for rest in snapshot.children.allObjects as! [DataSnapshot] {
guard let value = rest.value as? Dictionary<String,Any> else { continue }
guard let make = value["Cars"] as? String else { continue }
let cars = carStruct(cars: make)
self.cars.append(cars)
}
self.cars = self.cars.reversed(); self.tableView.reloadData()
})
}
#IBOutlet weak var tableView: UITableView!
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cars.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellMake")
let label1 = cell?.viewWithTag(21) as! UILabel
label1.text = cars[indexPath.row].cars
return cell!
}
}
I think you should make another struct for holding data that is inside of the model of the car (so, for this struct you should dig little bit deeper). As for retrieving data now, I suggest you to read this article, which helped me a lot not long ago.

Resources