Populating an UICollectionView to Firebase - ios

I'm trying to populate a collection view with data from a Firebase Database. I'm making following call in my viewdidload function:
ref = FIRDatabase.database().reference(withPath: "Profiles")
handle = ref.queryOrdered(byChild: title!).observe(.value, with: { snapshot in
var items: [Profiles] = []
if snapshot.value is NSNull {
print("NIL!!")
} else {
for item in snapshot.children {
let profile = Profiles(snapshot: item as! FIRDataSnapshot)
items.append(profile)
}
self.profiles = items
self.collectionView?.reloadData()
}
}) { (error) in
print(error.localizedDescription)
}
I'm getting the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value
and the compiler highlights the following piece of code:
handle = ref.queryOrdered(byChild: title!).observe(.value, with: { snapshot in
I'm not understanding what the issue is, and dont understand how to fix it?!

It sounds like you're confusing the UIViewController's title member with the Firebase child you're using the query for. If you have a child named title in your data structure and want to query based on that, just replace your query statement with this:
ref.queryOrdered(byChild: "title").observe(.value, with: { snapshot in
// your code
})
The only way you'd get the error you're getting is if the variable you're using (title) has nil.

Related

the retrieved data doesn't append in my array swift4

I'm trying to append "the retrieved data -Keys- from firebase" into an array but it doesn't work
This is the for loop output #2 the retrieved keys
This the keys from firebase
This is the code
let ref = Database.database().reference()
ref.child("Faculty ").observe(.value, with: { (snapshot) in
if let result = snapshot.children.allObjects as? [DataSnapshot] {
for child in result {
let FacultyName = child.key as! String
print(FacultyName)
self.NamesofFac.append(FacultyName)
}
}
})
for i in 0...self.NamesofFac.count {
print(self.NamesofFac.count)
print(" line")
print(self.NamesofFac)
The problem you are having is the Firebase Observe function give a callback in the form of a (snapshot).
It takes a bit of time to go to the web to get the data, therefore, firebase returns the data asynchronously. Therefore your code in your for loop will run before your firebase data has been returned. At the time your for loop code runs the array is still blank. But the for loop code in a separate function as you see in my sample code and call it straight after your for loop inside your firebase observe call.
Try this instead:
override func viewDidLoad() {
getFirebaseData()
}
func getFirebaseData() {
let ref = Database.database().reference()
ref.child("Faculty ").observe(.value, with: { (snapshot) in
if let result = snapshot.children.allObjects as? [DataSnapshot] {
for child in result {
let FacultyName = child.key as! String
print(FacultyName)
self.NamesofFac.append(FacultyName)
}
printNames()
}
})
}
func printNames() {
for i in 0...self.NamesofFac.count {
print(self.NamesofFac.count)
print(" line")
print(self.NamesofFac)
}
}
This was it won't print the names until they have been fully loaded from firebase.
PS: Your naming conventions are incorrect. You seem to be naming variables with a capital letter. Variables should be camel case. Classes should start with a capital.

My firebase int returns nil

I'm trying to pull an int from my firebase db however when I try and set my variable it returns nil.
ref = Database.database().reference()
let UserUID = Auth.auth().currentUser?.uid as? String
ref.child("users").child(UserUID!).child("MaxVal").observeSingleEvent(of:
.value, with: { (snapshot) in
let snap = snapshot.value as? Int
self.MaxValFB = snap! //this returns nil
}) { (error) in
print(error.localizedDescription)
}
Any help apreiciated!
EDIT: upon printing its result it returns
Optional( null)
also here is the db json file
{
"users" : {
"Optional(\"njcfCQaIIhZS9qrqM9OFLqTS7yA2\")" : {
"MaxVal" : 1
}
}
}
I think the problem is this "Optional(\"njcfCQaIIhZS9qrqM9OFLqTS7yA2\")" , when you are saving the data to firebase , you are giving it the id without unwrapping the optional and when you get the value you are unwrapping it like UserUID! , so it gives "njcfCQaIIhZS9qrqM9OFLqTS7yA2" , hence these are two different values.
So I think you should unwrap the userid when you save the data to firebase or try to get it without unwrapping i.e child(UserUID) without ! , although I would suggest to go with the first option.

Firebase get child name by value and remove it

My JSON looks like this:
users
username1: "WWOdh96Yr3Qs4N3GWDVq3OlQFfB2"
username2: "RJ6PztTLmsg222oUygWHtWpVHdg1"
I would like to get "username1" by their key which is (auth.uid)! and if its found i want to delete it, So after delete it will be looks like this:
users
username2: "RJ6PztTLmsg222oUygWHtWpVHdg1"
.
self.ref.child("users").queryOrderedByValue().queryEqual(toValue: user?.uid).observe(.value, with: { snapshot in
if snapshot.exists() {
print("\(snapshot.value)")
snapshot.ref.child(snapshot.value as! String).removeValue() // this deleting every thing which is WRONG!
} else{
print("Not found--")
}
self.ref.removeAllObservers()
})
}
This code deleting everything in users. I just want to delete specific user.
First of all, my approach is if I want to query 1 value at 1 moment, like you are doing, I do a observeSingleEvent (is this the best approach?). But to solve your problem, you forgot to add your "users" path. Below code is more safe to use, since you force unwrap (which is not recommend for this case):
let dataRef = self.ref.child("users")
dataRef.keepSynced(true)
if let usersUID = Auth.auth().currentUser?.uid{
dataRef.child("users").queryOrderedByValue().queryEqual(toValue: usersUID).observeSingleEvent(.value, with: { snapshot in
print(snapshot)
let values = snapshot.value as? NSDictionary
for (key, value) in values{
print(value) // does this print the uid?
print(key) // or this one?
self.ref.child("users/\(key)").removeValueWithCompletionBlock({ (err, ref) in
if err != nil {
print(err)
} else {
print(ref)
print("Removed")
}
})
}
})
}
Try to add this, right after the print(snapshot)

Segue Issue when switching views

I am currently getting an error on my app when I am performing a segue to another view which is performed by clicking on an Image View.
The error says: fatal error: unexpectedly found nil while unwrapping an optional value. I am not sure why this is happening but below is an image where the error is occuring. I am assuming there is something wrong with the segue because the error occurs when clicking the button. However the error is highlighted on this piece of code which is confusing me?
This is the code:
func loadComments() {
let postCommentRef = FIRDatabase.database().reference().child("post-comments").child(self.postId)
postCommentRef.observe(.childAdded, with: {
snapshot in
print("observe key")
print(snapshot.key)
FIRDatabase.database().reference().child("comments").child(snapshot.key).observeSingleEvent(of: .value, with: {
snapshotComment in
if let dict = snapshot.value as? [String: Any] {
//Retrieving from the database - post Model created class
let newComment = Comment.transformComment(dict: dict)
self.getUser(uid: newComment.uid!, completed: {
self.comments.append(newComment)
self.tableView.reloadData()
})
}
})
})
}

Update Value Firebase Swift 3

I'm having trouble updating a value in my Firebase database with the key status. I just can't figure out how to access the child(id) in which it is an autoID. Should I have an attribute in my Swift 3 Entity? Or is there a child(autoID) or something similar? I'm new in Firebase and Swift 3. Can any one help? This is my code:
self.ref?.child("requests").queryOrdered(byChild: "Sender").queryEqual(toValue: self.items[indexPath.row].Sender).setValue("2", forKey: "status"))
Swift 3 && Firebase 3
Hope this code will be help you...
// create the reference you want to observe
let myRequestRef = FIRDatabase.database().reference().child("requests").queryOrdered(byChild: "Sender").queryEqual(toValue: self.items[indexPath.row].Sender)
// check the sender value
myRequestRef.observeSingleEvent(of: .value, with: { (snapshot) in
//get the sender key
let senderKey = snapshot.key as String
// create status ref for new status value
let statusRef = FIRDatabase.database().reference().child("requests").child(senderKey)
// create new dict for status value
let newValue = ["Status": 2] as [String: Any]
statusRef.updateChildValues(newValue, withCompletionBlock: { (error, _) in
if error != nil {
print(error?.localizedDescription ?? "Failed to set status value")
}
print("Successfully set status value")
// Update your UI
DispatchQueue.main.async {
// Do anything with your UI
}
})
}) { (error) in
print("Failed to get snapshot", error)
}
Try moving your code inside .observe. This will allow you to get the status and check that it's accessing the right child. By using the child path below, it will override the status value but not the rest of the values inside the child.
self.ref?.child("requests").queryOrdered(byChild: "Sender").queryEqual(toValue: self.items[indexPath.row].Sender).observe(.value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
if value != nil {
print(value)
print(value["status"])
// If status is what you want, and prints out the correct status and
// correct child item
// Update the status
self.ref.child("requests/\(self.items[indexPath.row].Sender)/status").setValue("2")
}
})
I haven't tested the code above, but you should be able to make minor tweaks to get it to work in your code and on your firebase database.
You can update status value as below:
self.ref?.child("requests").queryOrdered(byChild: "Sender").queryEqual(toValue: self.items[indexPath.row].Sender).observe(.value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
if value != nil {
self.ref.child("requests/(self.items[indexPath.row].Sender)").updateChildValues(["status":"2"])
}
})

Resources