Read values from database into Array - ios

I'm trying to read from the database and place the values into an array of strings. However, when I try to push the values into an array then print the array the app crashes.
var pets: [String]?
override func viewDidLoad() {
super.viewDidLoad()
let userRef = FIRDatabase.database().reference().child("users").child((FIRAuth.auth()?.currentUser?.uid)!).child("pets")
userRef.observeSingleEvent(of: .value, with: { snapshot in
if let snap = snapshot.value as? Bool {
print("no values")
} else if let snap = snapshot.value as? NSDictionary {
for value in snap {
print(value.key as! String) // Prints out data in the database
self.pets?.append(value.key as! String)
}
print(self.pets!)
}
})
Does anybody know why the print(value.key as! String) prints out the data but then when I print out the array the app crashes with unexpectedly found nil while unwrapping an Optional value?

You never initialize pets. You declare it as an optional but never assign it a value. Why not change your code to the following:
var pets = [String]() // start with an empty array
override func viewDidLoad() {
super.viewDidLoad()
let userRef = FIRDatabase.database().reference().child("users").child((FIRAuth.auth()?.currentUser?.uid)!).child("pets")
userRef.observeSingleEvent(of: .value, with: { snapshot in
if let snap = snapshot.value as? Bool {
print("no values")
} else if let snap = snapshot.value as? NSDictionary {
for value in snap {
print(value.key as! String) // Prints out data in the database
self.pets.append(value.key as! String)
}
print(self.pets)
}
})

Your array is nil when you try to force-unwrapping using:
print(self.pets!)
As you are using self.pets?.append() you don't have any problem because you are using the chaining of optionals, but your array, in fact, is nil at that time because you forgot to initialize it before use it. If you instead use self.pets!.append() you will see a runtime error instead.
So as #rmaddy suggest you can initialize the array at the beginning or just inside your viewDidLoad() it's up to you.
I hope this help you.

Related

Firebase returns nil when fetching data

I had a problem with fetching data, seems to be working now, but instead of observing .childAdded, i need to observe value.
My Current code function is:
func fetchJobs() {
ref.child("jobposts").observe(.childAdded) { (snapshot) in
guard let dictionary = snapshot.value as? [String:Any] else { return}
var job = JobData()
job.title = (dictionary["title"] as! String) <-- Error in any of the job.*
job.company = (dictionary["company"] as! String)
job.city = (dictionary["city"] as! String)
job.salary = (dictionary["salary"] as! String)
job.creator = (dictionary["creator"] as! String)
self.jobs.append(job)
}
}
When i change .observe(.childAdded) to .observe(.value) i get an error :
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Any ideas what could cause this?
Using print(dictionary) prints all the documents, maybe i need to map them somehow? Thank you in advance
When you observe a .value event for a list of nodes, you need to loop over snapshot.children to get the individual nodes. From the documentation on listening for value events for lists:
_commentsRef.observe(.value) { snapshot in
for child in snapshot.children {
...
}
}
The ... is where your current code inside the .childAdded listener goes.

Can't seem to save local array in Swift

So I'm running into a problem where I can't seem to save the contents of a local array outside of a for loop. This code iterates through notifsTop (which is a dictionary) and saves the values into another array. However, outside of the for loop, the contents of tempnotifsarray are empty, which doesn't make sense to me since I appended them to an array that is outside of the loop block. I have been struggling with this for some time and can't figure out what is going on. Any help would be appreciated, thanks!
func createArray() -> [notificationLabel] {
let newUserInfo = Auth.auth().currentUser
let uid = newUserInfo?.uid
self.ref = Database.database().reference()
let practionerRef = self.ref.child("users").child(uid!)
var tempnotifsArray: [notificationLabel] = []
practionerRef.observeSingleEvent(of: .value, with: {(snapshot) in
let value = snapshot.value as? NSDictionary
if let notifsTop = value?["Notifications"] as? NSDictionary { //top of the notifications hierarchy
for (_, myValue) in notifsTop {
// Iterate in here
//self.notifications.append(myValue)
let notification = notificationLabel(label: myValue as! String)
tempnotifsArray.append(notification)
//if I print here the array is full with the values I want
}
}
})
print(tempnotifsArray) //comes out as []
return tempnotifsArray
}

Firebase found nil while unwrapping value

I am new to Firebase and I am trying to get the children from a DataSnapshot and add the keys to a list. But I am getting an error. Am i not unwrapping the data correctly or what am i doing wrong?
var arr: Array<String> = []
override func viewDidLoad() {
super.viewDidLoad()
populateArray()
print(arr)
func populateArray(){
ref.child("Sept24 - Oct 24").observeSingleEvent(of: .value, with: { (snapshot) in
print(snapshot.childrenCount)
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? DataSnapshot {
//print(rest.key)
self.arr.append(rest.key)
}
DispatchQueue.main.async{
self.sideMenuTable.reloadData()
}
})
print(arr)
}
arr is a global array with type string and i am calling populateArray() in the viewDidLoad() function.

Can't modify array because of for loop in swift?

I've been struggling with this all day, it doesn't seem to make any sense because I have very similar code that is working fine. I've tried everything, I've tried making a separate method that returns a string array, but none of it has worked. Every time, the postIDs array is set to null when accessed outside of the bracket followed by the parentheses (after the line reading "print(self.postIDs)"). Thanks for any help you could give me.
var postIDs = [String]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
let ref = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
ref.child("users").child(uid).child("saved").observeSingleEvent(of: .value, with: { snapshot in
var ids = [String]()
let saved = snapshot.value as! [String:AnyObject]
for (elem, _) in saved {
ids.append(elem)
}
self.postIDs = ids
print(self.postIDs) // returns the values I would expect
})
ref.removeAllObservers()
guard self.postIDs.count >= 1 else {return} // postIDs count is equal to 0 here, and when I print postIDs the result is []
It is because
ref.child("users").child(uid).child("saved").observeSingleEvent(of: .value, with: { snapshot in
var ids = [String]()
let saved = snapshot.value as! [String:AnyObject]
for (elem, _) in saved {
ids.append(elem)
}
self.postIDs = ids
print(self.postIDs) // returns the values I would expect
})
works on background and other line of code executes before the callback came
Check the following code
override func viewDidLoad() {
super.viewDidLoad()
usersTableView.dataSource = self
usersTableView.delegate = self
// getSnapShot()
let databaseRef = Database.database().reference()
databaseRef.child("Users").observe(.value, with: { (snapshot) in
if snapshot.exists() {
self.postData = snapshot.value! as! [String : AnyObject]
self.postData.removeValue(forKey: self.appDelegate.KeyValue)
// self.getUserNames(Snapshot: self.postData)
}
else{
print("No users")
}
print(self.postData) //Does not return nil
self.getSnapShot() //Take snapshot outside paranthesis
})
print(self.postData) //Returns nil
}
func getSnapShot() {
print(self.postData) //Value of Snapshot is printed
}

NSDictionary has value of none

I want the user to add Friends. However whenever I click on addFriend button I get a breakpoint with an thread 1. There is no further error information rather than 11db.
I have found out by now that the NSDictionary of "otherUser" has the value of none. Thats the reason everything is not working. However I have no clue why that is. Out of the same NSDictionary , I get the username and the profile Pic. Why is it nil then?
var otherUser: NSDictionary?
override func viewDidLoad() {
super.viewDidLoad()
databaseRef.child("user").child(self.otherUser?["uid"] as! String).observe(.value, with: { (snapshot) in
let uid = self.otherUser?["uid"] as! String
self.otherUser = snapshot.value as? NSDictionary
self.otherUser?.setValue(uid, forKey: "uid")
}) { (error) in
print(error.localizedDescription)
}
}
#IBAction func addFriend(_ sender: Any) {
if self.befreunden.titleLabel?.text == "Als Freund hinzufügen" {
let friendRef = "befreundet/\(self.loggedinUSerData?["uid"] as! String)/\(self.otherUser?["uid"] as! String)"
let BefreundenData = ["username":self.otherUser?["username"] as? String,
"ProfilePic":self.otherUser?["urltoImage"] as! String!]
let childUpdats = [friendRef:BefreundenData]
databaseRef.updateChildValues(childUpdats)
}else {
FreundeAnzahl = self.otherUser?["AnzahlFreunde"] as! Int + 1
}
}
Edit:
I've just found out, that the NSDictionary of otherUser has all the values needed inside the viewdidLoad. But as soon as I call the uid of the otherUser in the addFriend function it gives back a value of nil.
Why is it happening?
I fixed the issue by simple giving the uid of the otheruser NSDictionary to a new variable which I created in the viewdidLoad.
This way I do not face any issues regarding unwrapping optionals later on.

Resources