Swift 3.x iOS 10.
Trying to understand Databases in firebase. Imported some JSON data into my app and managed to read it back. This the code.
let rootRef = Database.database().reference(withPath: "0")
print("\(rootRef.key)")
let nextRef = rootRef.child("identity")
print("\(nextRef)")
nextRef.observe(.value, with: { snapshot in
print("\(snapshot.value)")
})
Which works, my data looks like this ...
But how to do this if I want to traverse the database, looking at record 2, record 3 etc etc where I am not sure how many records I actually got.
Ok, I found it, well something that works...
let rootRef = Database.database().reference()
rootRef.observe(.value, with: { snapshot in
print("dump \(snapshot.children.allObjects)")
})
I post for posterity :)
Related
I know this question is asked a lot, but none of the solutions seem to be working for me(I have been trying multiple solutions from threads like Read data from firebase swift but it doesnt print anything to my console).
I am trying to retrieve the type of user from my database, but I dont know how to.
func pushUserInfo(){
let ref = Database.database().reference()
let infoDict = ["First name": firstName.text!, "Last name": lastName.text!, "hours": 0, "isUser" : "user"] as [String : Any]
let users = ref.child("users").child(username)
users.setValue(infoDict)
}
The part that says ["type": "user"] has two options, either "user" or admin
The screenshot above is of the Firebase realtime database.
I am trying to retrieve the type of the user, but I have no idea how. Please help me figure this out, and if possible, explain the code, because I dont really understand too much about Firebase in general. I tried reading their firebase docs, but I still dont really get it.
It looks like you're setting the data fine except that your username property appears to be a concatenated string of two optionals (maybe firstName.text and lastName.text. So this will make it impossible to query. The first step is to unwrap these into a string:
let username = "\(firstName.text!) \(lastName.text!)"
Once you've done that, you can query for that data like this:
let username = "\(firstName.text!) \(lastName.text!)"
let ref = Database.database().reference().child("users/\(username)")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
// Now you can access the type value
let value = snapshot.value as? NSDictionary
let type = value?["type"] as? String ?? ""
}) { (error) in
print(error.localizedDescription)
}
You may also want to reconsider having spaces in your property names (maybe use lastName instead of last name). It will be easier for your code later on.
Super newbie! I just want to practice reading and writing for Firebase. My write code works! I've consulted dozens of examples online and still can't get the read portion working.
As a newbie, I've also tried some simple debug techniques but no help.
Exactly how do I fix this code so that the read happens (and I know it happened because the code prints to terminal)?
I'd really like a Swift 4 based solution, thanks.
My repo
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var ref:DatabaseReference!
var refHandle:DatabaseHandle!
ref = Database.database().reference()
ref.child("test").setValue("name: Bruce")
//Nothing below works
refHandle = ref.child("test").observe(DataEventType.childAdded, with: { (snapshot) in
let info = snapshot.value as? String
print(info as Any)
})
}
Note that my Firebase DB is enabled for READ and WRITE. I have also tried observeSingleInsance (or whatever it is when you read just once).
I know the write works because i can see the data in the Firebase console
I believe your problem is in setValue("name: Bruce"), where you set the node "test" to "name: Bruce", as opposed to "name": "Bruce"
if you change that to say
updateChildValues(["name": "Bruce"])
surely it would work.
Go to your Firebase console, and perform following steps which is identify in image.
Read like that as you currently trying to listen to child add , so replace childAdded with value , Also you should wait until write process happens and then read , suppose launch app again for read only
refHandle = ref.child("test").observeSingleEvent(of: .value, with: { (snapshot) in
let info = snapshot.value as? String
print(info as Any)
})
Do you have this enabled? Then try changing it to
Database.database().isPersistenceEnabled = false
Otherwise try this and print the snapshot you get (You don't actually need the handle):
ref.child("test").observe(.value, with: { (snapshot) in
print(snapshot)
})
I want to fetch the required app version number when the app starts. But I can't get the right key.
I have this code to fetch. I use observe single event because I use this method to check the required app version number. This method is only fired when the app starts to do the check.
func getVersion(completionHandler: #escaping (Result<Any?>) -> ()) {
let ref: DatabaseReference! = Database.database().reference().child("version").child("IOS")
ref?.observeSingleEvent(of: .value , with: { snapshot in
if snapshot.exists() {
let recent = snapshot.value as! NSDictionary
print(recent)
}
})
}
But it is returning old results? I have isPersistenceEnabled enabled at my Appdelegate.
This is the database structure:
I get no results when I use Database.database().reference().child("version").child("IOS").
snapshot.exists is false when I use that.
What I previously had was:
- version
|
IOS - 1.0
And i get result when I use Database.database().reference().child("version"), namely {iOS => 1.0}. I don't get it because it was my old structure.
The Firebase Realtime Database synchronizes and stores a local copy of the data for active listeners. In addition, you can keep specific locations in sync.
let scoresRef = Database.database().reference(withPath: "scores")
scoresRef.keepSynced(true)
The Firebase Realtime Database client automatically downloads the data at these locations and keeps it in sync even if the reference has no active listeners. You can turn synchronization back off with the following line of code.
scoresRef.keepSynced(false)
Haven't really tried it but it should work.
The observeSingleEvent method is used for data that doesn't really change, and as such it will fetch from the local cache if you have persistence enabled.
This Android solution (https://stackoverflow.com/a/40477280/883413) provides a workaround by using an alternate method, runTransactonBlock.
Transactions give an opportunity to edit any data before they are saved. Here, we can simply accept the data as correct as we are only interested in reading the latest values.
let ref: DatabaseReference! = Database.database().reference().child("version").child("IOS")
ref.runTransactionBlock({ (data) -> TransactionResult in
return TransactionResult.success(withValue: data)
}, andCompletionBlock: { (error, success, snapshot) in
if let snapshot = snapshot, snapshot.exists() {
if let recent = snapshot.value as? NSDictionary {
print(recent)
}
}
})
I'm building a basic chat app with swift for iOS with firebase realtime database.
The Messages are observed with a limit for the least 10.
Now, I want to implement the functionality of loading earlier send messages. Currently I'm trying to achieve this by using this function:
let query = threadRef.child("messages").queryOrderedByKey().queryStarting(atValue: "2").queryLimited(toLast: 2)
Which returns this query:
(/vYhNJ3nNQlSEEXWaJAtPLhikIZi1/messages {
i = ".key";
l = 2;
sp = 2;
vf = r;
})
And this should give me the data:
query.observeSingleEvent(of: .value, with: { (snap) in
But it just limits the query and not set the start point to a specific position.
Here is the firebase database structure:
messages
-Kgzb3_b26CnkTDglNd8
date:
senderId:
senderName:
text:
-Kgzb4Qip6_jQdKRWFey
-Kgzb4ha0KZkLZeBIaxW
-Kgzb577KlNKOHxsQo9W
-Kgzb5cqIVMhRmU019Jf
Anyone have an idea on how to implement a feature like that?
Okay I finally found a way to do what I wanted.
First of all I misunderstood the way to access data from Firebase.
This is now how I get the query:
let indexValue = messages.first?.fireBaseKey
let query = messageRef.queryOrderedByKey().queryEnding(atValue:indexValue).queryLimited(toLast: 3)
1) get the FireBase key I previously saved to my custom chat messages
2) construct the query:
order it by key
set the ending to oldest message
limit the array to query to desired length
Then to actually get the query I used:
query.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children.dropLast().reversed() {
let fireSnap = (child as! FIRDataSnapshot)
//do stuff with data
}
})
1) get the query as a single event
2) iterate over children and I needed to dropLast() to make sure I don't have any duplicated messages and reverse it to get the correct order.
3) cast the current child as a FIRDataSnapshot to access the data
Since I couldn't find a simple example for this so I thought I leave my solution here incase other people running into the same problem.
How do I retrieve a value (other than username and user id, which seem easier to get) for the current user from the database.
Ironically, I can set the value as follows and that works just fine:
let databaseRef = FIRDatabase.database().reference()
userID = (FIRAuth.auth()?.currentUser?.uid)! as String
databaseRef.child("users").child(userID!).child("TermCond").setValue("Yes")
But for the life of me I cannot work out what to put instead of setValue if I simply want to retrieve the current TermCond value. I thought just using value as for example in
let DesiredValue = databaseRef.child("users").child(userID!).child("TermCond").value as? String
Would suffice, but nothing works. I am confused why retrieving the value should be more difficult than setting it.
To "read" a value from Firebase, you need to add a reference listener that gets called every time that value changes.
In your case, that could be something like:
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("users").child(userID!).child("TermCond").observe(FIRDataEventType.value, with: { (snapshot) in
let desiredValue = snapshot.value as? String
})
This block of code will get triggered every time your value changes. If you only want to read it once, you can use observeSingleEvent:of:with instead of observe:with.
This is as described in the Firebase documentation: https://firebase.google.com/docs/database/ios/read-and-write
I recommend you read their entire Documentation to get an idea of how Firebase works, as it is very different from traditional databases.
I can also recommend the following tutorial if you'd like to learn a bit more about the Firebase Database and how it works: https://www.raywenderlich.com/139322/firebase-tutorial-getting-started-2
I've solved this now (based on Aleksander's reply). The way I did it is as follows.
databaseRef.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
self.desiredValue = value?["TermCond"] as? String ?? ""
self.LabelToShow.text = self.desiredValue!
}) { (error) in
print(error.localizedDescription)
}
This works absolutely fine and shows the value of TermCond in the LabelToShow on my iOS screen.