I'm running the code below to see if a user that opens the app is already logged in, and then to check if they've set up a profile. I'm having trouble checking for the null value value returned from the profile check
override func viewDidLoad() {
super.viewDidLoad()
//Check to see if user is already logged in
//by checking Firebase to see if authData is not nil
if ref.authData != nil {
//If user is already logged in, get their uid.
//Then check Firebase to see if the uid already has a profile set up
let uid = ref.authData.uid
ref.queryOrderedByChild("uid").queryEqualToValue(uid).observeSingleEventOfType(.Value, withBlock: { snapshot in
let profile = snapshot.value
print(profile)
})
In the last line when I print(profile), I either get the profile information, or
<null>
how do i check for this value?
if profile == nil
does not work
If I do
let profile = snapshot.value as? String
first, then it always returns nil even if there is a snapshot.value
Take advantage of the exists() method to determine if the snapshot contains a value. To use your example:
let uid = ref.authData.uid
ref.queryOrderedByChild("uid").queryEqualToValue(uid)
.observeSingleEventOfType(.Value, withBlock: { snapshot in
guard snapshot.exists() else{
print("User doesn't exist")
return
}
print("User \(snapshot.value) exists")
})
.
Here's another handy example, Swift4
let path = "userInfo/" + id + "/followers/" + rowId
let ref = Database.database().reference(withPath: path)
ref.observe(.value) { (snapshot) in
let following: Bool = snapshot.exists()
icon = yesWeAreFollowing ? "tick" : "cross"
}
You may want to explore another option: since you know the uid of the user and therefore the path to that user, there's no reason to query. Queries add unnecessary overhead in situations where you know the path.
For example
users
uid_0
name: "some name"
address: "some address"
You are much better off observing the node in question by value, which will return null if it doesn't exist
ref = "your-app/users/uid_0"
ref.observeEventType(.Value, withBlock: { snapshot in
if snapshot.value is NSNull {
print("This path was null!")
} else {
print("This path exists")
}
})
in the event you are storing it some other way; perhaps
random_node_id
uid: their_uid
name: "some name"
then a query would be in order, like this
ref.queryOrderedByChild("uid").queryEqualToValue(their_uid)
.observeEventType(.Value, withBlock: { snapshot in
if snapshot.exists() {
print("you found it!")
}
});
Related
I setup Firebase database like this:
dataS
- LjYal4ijEdjfafe
- email: "abc#xxx.org"
- firstname: "aa"
- lastname: "bb"
And I cannot retrieve data "lastname", it always return nil.
let ref = Database.database().reference()
ref.queryOrdered(byChild: "email").queryEqual(toValue: email1).observeSingleEvent(of: .value, with: { (snapshot) in
if !snapshot.exists() {
print("cannot find in firebase")
return
}
let value1 = snapshot.value as? NSDictionary
let lastnameP = value1?["lastname"] as? String ?? ""
print(lastnameP)
There are a few issues with the code.
The first is when observing by .value, all of the matches will be returned whether it be 1 or 1000 so that returned DataSnapshot will need to be iterated over to access the child data, even if there's 1. If using .childAdded, it will return one at a time in the snapshot if using .observe, and only the first using .childAdded.
Second thing is the reference is pointing at the root reference. It appears dataS may be a child of the root
root_firebase
dataS
uid
email
firstname
lastname
if not, then keep in mind this code matches that structure.
Last thing is to make it more Swifty and use modern function calls and add a little error checking in case the lastname node is not found with the nodes being read.
let email1 = "email to query for"
let ref = Database.database().reference()
let nodeToQueryRef = ref.child("dataS")
nodeToQueryRef.queryOrdered(byChild: "email")
.queryEqual(toValue: email1)
.observeSingleEvent(of: .value, with: { snapshot in
if snapshot.exists() == false {
print("cannot find in firebase")
return
}
let returnedSnapshotArray = snapshot.children.allObjects as! [DataSnapshot]
for snap in returnedSnapshotArray {
let key = snap.key
let lastName = snap.childSnapshot(forPath: "lastname").value as? String ?? "No Last Name"
print(key, lastName)
}
})
I'm trying to fetch the first key from my firebase database but for some reason nothing is being printed out. How can I get the first key from my firebase database using .childAdded
let userMessagesRef = Database.database().reference().child("user-message").child(uid).child(userId)
userMessagesRef.observe(.childAdded, with: { (snapshot) in
guard let first = snapshot.children.allObjects.first as? DataSnapshot else { return }
print(first)
This in incredibly easy if you literally are asking how to only ever get the first child of a node. Here's how to only get the first child of a /users node
func getFirstChild() {
let usersRef = self.ref.child("users")
usersRef.observeSingleEvent(of: .childAdded, with: { snapshot in
print(snapshot)
})
}
or
print(snapshot.key)
if you just want the key.
Or, if you want to use a query to do the same thing
func getFirstChildAgain() {
let usersRef = self.ref.child("users")
let query = usersRef.queryOrderedByKey().queryLimited(toFirst: 1)
query.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot)
})
}
The child_added event is typically used when retrieving a list of items from the database. Unlike value which returns the entire contents of the location, child_added is triggered once for each existing child and then again every time a new child is added to the specified path. The event callback is passed a snapshot containing the new child's data. For ordering purposes, it is also passed a second argument containing the key of the previous child.
From: Read and Write Data on iOS
Per your requirements, this is possible in .value and childAdded.
var child_array = [String:String]
let userMessagesRef = Database.database().reference().child("user-message").child(uid).child(userId)
userMessagesRef.observe(.childAdded, with: { (snapshot) in
let value = snapshot.value as? String ?? "Empty String"
let key = snapshot.key
child_array[key] = value;
}) { (error) in
print(error.localizedDescription)
}
then:
if let first = child_array.first?.key {
print(first) // First Key
}
Big NOTE: child_added randomly collects this data, you should never use it to sort your data
I have been searching for an answer and could not find it.
I am using Swift 3.
I have a path, let's say firebase/products, and I want to see if a specific product has a key "MainImage". So naturally I'd do something like
Database.Child("Products").Child("ProductID").HasChild("MainImage")
But there's no method like "HasChild", or "Exists" or anything similar I could find out. Does anyone have the solution for this ?
There is no method that can check for that, you are going to listen to that child and if it has a nil value, then it does not exist.
var ref = FIRDatabase.database().reference()
let ProductID = 64646477343
let requestListenRefo = ref.child("Products/\(ProductID)/MainImage")
requestListenRefo.observe(FIRDataEventType.value, with: { (snapshot) in
let value = snapshot.value as? String
if(value == nil)
{
// doesn't exist
}
})
There is a way to check existence of the snapshot using snapshot.exists()
Swift
dbRef = FIRDatabase.database().reference()
dbRef.child("Users/user1").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists(){
print("user1 exists")
}else{
print("user1 exists doesn't exists")
}
})
I have two issues with the snippet below.
I have get duplication in my TableView.
When I search for something that returns a result, and I tried searching for another thing that returns a result, the existing result will be the one showing not the new result, for example:
a. I search for "ola" and my TableView returns a list of -> olabode, olatunde, olaide.
b. Then I searched for "bisi", if found matching query for "bisi" I still get the query result for "ola".
func searchView(_ searchView: AZSearchViewController, didTextChangeTo text: String, textLength: Int) {
self.resultArray.removeAll()
searchView.reloadData()
guard text != "" else {
return
}
AppFirRef.userRef.queryOrdered(byChild: "username")
.queryStarting(atValue: text)
.queryEnding(atValue: text + "\\uf8ff")
.observe(.value, with: { (snapshot) in
if (snapshot.value is NSNull) {
print("not found")
} else {
print("found")
self.resultArray.removeAll()
searchView.reloadData()
print("\(snapshot.value)")
for case let snap as FIRDataSnapshot in snapshot.children {
guard let value = snap.value as? [String : Any] else { continue }
//print("\(snap.key)")
print(value)
let user = LContact(value: value, searchUserId: snap.key)
self.set.add(user)
if let username = user.username{
self.resultArray.append(username.lowercased())
searchView.reloadData()
}
}
}
})
}
It might be too late, but change
.observe(.value, with: { (snapshot) in
...
)}
to
.observeSingleEvent(of: .value, with: { (snapshot) in
...
)}
see my answer to this question for the explanation; it applies to you as well because you are also appending to the array every time the data at your reference path changes (such as when someone on another device changes data in the userRef reference path.
This may be a simple answer, so apologies in advance, but I'm stuck because I'm still getting head wrapped around how Firebase works. I want to query a Firebase Database based on unix date data that is saved there and then take the related "Unique ID" data and put it into an array.
The data in Firebase looks like this:
posts
node_0
Unix Date: Int
Unique ID Event Number: Int
node_1
Unix Date: Int
Unique ID Event Number: Int
node_2
Unix Date: Int
Unique ID Event Number: Int
What I have so far is as follows. The query part seems to be working as expected. Where I'm struggling is how to put the "Unique ID Event Number" data into an array. This is the approach that seemed closest to success, which is based on this post, but I get an error that child has no member of "value".
// Log user in
if let user = FIRAuth.auth()?.currentUser {
// values for vars sevenDaysAgo and oneDayAgo set here
...
let uid = user.uid
//Query Database to get the places searched by the user between one and seven days ago.
let historyRef = self.ref.child("historyForFeedbackLoop/\(uid)")
historyRef.queryOrdered(byChild: "Unix Date").queryStarting(atValue: sevenDaysAgo).queryEnding(atValue: oneDayAgo).observeSingleEvent(of: .value, with: { snapshot in
if (snapshot.value is NSNull) {
print("error")
} else {
for child in snapshot.children {
if let uniqueID = child.value["Unique ID Event Number"] as? Int {
arrayOfUserSearchHistoryIDs.append(uniqueID)
}
}
}
})
} else {
print("auth error")
}
Any ideas are greatly appreciated!
Try using this:-
historyRef.queryOrdered(byChild: "Unix Date").queryStarting(atValue: sevenDaysAgo).queryEnding(atValue: oneDayAgo).observeSingleEvent(of: .value, with: { snapshot in
if let snapDict = snapshot.value as? [String:AnyObject]{
for each in snapDict{
let unID = each.value["Unique ID Event Number"] as! Int
arrayOfUserSearchHistoryIDs.append(unID)
}
}else{
print("SnapDict is null")
}
})
I ended up re-working how I read the Firebase data based on the approach outlined in this post. The actual working code I used follows in case it's helpful for someone else.
// Log user in
if let user = FIRAuth.auth()?.currentUser {
let uid = user.uid
// values for vars sevenDaysAgo and oneDayAgo set here
...
let historyRef = self.ref.child("historyForFeedbackLoop/\(uid)")
historyRef.queryOrdered(byChild: "Unix Date").queryStarting(atValue: sevenDaysAgo).queryEnding(atValue: oneDayAgo).observeSingleEvent(of: .value, with: { snapshot in
if (snapshot.value is NSNull) {
print("user data not found")
}
else {
for child in snapshot.children {
let data = child as! FIRDataSnapshot
let value = data.value! as! [String:Any]
self.arrayOfUserSearchHistoryIDs.append(value["Unique ID Event Number"] as! Int)
}
}
})
}