Why I cannot add data into Firebase in this way? - ios

I am doing a project which is concerned about Firebase, I have tried to upload the data to the Firebase as the code in the tutorial from the Firebase website:
// An index to track Ada's memberships
{
"users": {
"alovelace": {
"name": "Ada Lovelace",
// Index Ada's groups in her profile
"groups": {
// the value here doesn't matter, just that the key exists
"techpioneers": true,
"womentechmakers": true
}
},
...
},
"groups": {
"techpioneers": {
"name": "Historical Tech Pioneers",
"members": {
"alovelace": true,
"ghopper": true,
"eclarke": true
}
},
...
}
}
and I follow this structure to write my own data structure, which looks like this:
func pushUser() {
let username = self.username
let userid = FIRAuth.auth()?.currentUser?.uid
let userInfo : [String : Any] = ["username" : username,
"userID" : userid,
"sggestedRoutes" : "",
"myTracedRoutes" : "",
"routes": {
"usualInfo" : true,
"calcuInfo" : true
}
]
let userRef = FIRDatabase.database().reference()
userRef.child("user").childByAutoId().setValue(userInfo)
}
in Swift3, but the debugger says the nested routes{} is not correct, I am quite confused about this, could anyone give me a hint on this?
Kind regards
After received the advice, I make some change on the code, but it is still not working on the Route part:(
func pushUser() {
let username = self.username
let userid = FIRAuth.auth()?.currentUser?.uid
let userInfo : [String : Any] =
["username" : username,
"userID" : userid,
"sggestedRoutes" : "",
"uploadedRoutes" : "",
"myTracedRoutes" : "",
["Routes":
["usualInfo" : true,
"calcuInfo" : true]
]
]
let userRef = FIRDatabase.database().reference()
userRef.child("user").childByAutoId().setValue(userInfo)
}

Try adding the routes as ["routes": ["usualInfo": true, "calcuInfo": true]]
Don't forget the correct closures for both children "user info" and "routes"

Related

Retrieve Firebase Data from ChildbyAutoID Swift

I am saving data in swift, to a realtime firebase database using the following code:
guard let key = dbreference.child(("user-clients")).childByAutoId().key else { return }
let post = ["uid": userID,
"firstname": clientfirstname,
"lastname": clientlastname,
"dateofbirth": clientdateofbirth,
"haircolour": clienthaircolour,
"products": clientproduct]
let childUpdates = ["/user-clients/\(String(describing: user))/\(key)/": post]
dbreference.updateChildValues(childUpdates)
This automatically creates a child ID under the user that is logged in (so is my understanding?) and it works fine as my database is updating correctly.
The problem is - I am trying to read the first name and last name of each person and display in a table view (like a contact card) but I cannot 'pull out' the firstname and lastname data.
Here is my code to retrieve the data:
let dbref = Database.database().reference()
let me: String = (Auth.auth().currentUser?.uid)!
let key = dbreference.child(("users")).childByAutoId().key
//Access the databse and retrieve First and Last Names from child
dbref.child("user-clients").queryOrdered(byChild: me).observeSingleEvent(of: DataEventType.value) { (snapshot) in
if snapshot.exists() {
print("exists")
for child in snapshot.children {
let data = child as! DataSnapshot
//print(data.key)
print(data.value!)
if (data as AnyObject).hasChild("firstname") {
print("perfect")
} else {
print("does not exist")
}
if let firstname = snapshot.childSnapshot(forPath:"firstname").value as? String {
print(firstname)
}
if let lastname = snapshot.childSnapshot(forPath:"lastname").value as? String {
print(lastname)
}
}
}
It seems like I am not getting down another level as the console prints out all the contacts under the different autogenerated ID's. My JSON file looks like this:
{
"user-clients" : {
"Optional(\"4WNCGOaiIMTKAa12Pmi26w11hSb2\")" : {
"-M943knUA5JkpMuxygti" : {
"dateofbirth" : "7777",
"firstname" : "john",
"haircolour" : "blue",
"lastname" : "melon",
"products" : "09876543321",
"uid" : "4WNCGOaiIMTKAa12Pmi26w11hSb2"
},
"-M944HmLvM50rEc4qtM3" : {
"dateofbirth" : "12/12/12",
"firstname" : "basil",
"haircolour" : "yellow",
"lastname" : "brush",
"products" : "678990099",
"uid" : "4WNCGOaiIMTKAa12Pmi26w11hSb2"
},
"-M94C9yk7q6mQglQiaoR" : {
"dateofbirth" : "12/12/77",
"firstname" : "Homer",
"haircolour" : "yellow",
"lastname" : "Simpson",
"products" : "123456789",
"uid" : "4WNCGOaiIMTKAa12Pmi26w11hSb2"
},
"-M94CISM865qWAa8nbK-" : {
"dateofbirth" : "12/11/77",
"firstname" : "Marge",
"haircolour" : "Blue",
"lastname" : "Simpson",
"products" : "09876654433",
"uid" : "4WNCGOaiIMTKAa12Pmi26w11hSb2"
}
Any help would be greatly appreciated and I hope the above makes sense. Thanks in advance.

getting crash while retrieving dict from JSON by index wise

i am retrieving data by index from JSON let me show you my response
{
"contraventionsData" : [
{
"id" : "1",
"contravention_id" : "314",
"question" : "Last Gas Boiler Service date (Noted on boiler)",
"Options" : [
{
"action" : "Yes"
},
{
"action" : "Further Investigation \/ Maintenance"
},
{
"action" : "N\/A"
}
]
},
{
"id" : "2",
"contravention_id" : "314",
"question" : "Is Gas Boiler due a service? (Over 12 Months)",
"Options" : [
{
"action" : "Yes"
},
{
"action" : "Maintenance Attention"
},
{
"action" : "N\/A"
}
]
},
{
"id" : "3",
"contravention_id" : "314",
"question" : "Gas heating system \/ boiler working ok?",
"Options" : [
{
"action" : "Yes"
},
{
"action" : "Maintenance Attention"
},
{
"action" : "N\/A"
}
]
},
{
"id" : "4",
"contravention_id" : "314",
"question" : "Copy of Current Service Cert give to tenant",
"Options" : [
{
"action" : "Yes"
},
{
"action" : "Tenant to be provided with copy of current service cert"
},
{
"action" : "N\/A"
}
]
}
],
"message" : "Successfully.",
"success" : "1"
}
here is my response and i am retrieving by index like below
Code
func actionListAPI(){
let preferences = UserDefaults.standard
let uid = "u_id"
let acTkn = "acc_tkn"
let u_ID = preferences.object(forKey: uid)
let A_Token = preferences.object(forKey: acTkn)
let params = ["user_id": u_ID!, "access_token": A_Token!,"contraventions_id": conID!]
print(params)
SVProgressHUD.show()
Alamofire.request(reg6contraventionsquestions, method: .post, parameters: params).responseJSON(completionHandler: {(response) in
switch response.result{
case.success(let value):
let json = JSON(value)
print(json)
let data = json["contraventionsData"]
if data == []{
}else{
let sampleArray = data.array
let firstdict = sampleArray![0]
print(firstdict)
let question = firstdict["question"].stringValue
self.lblQue1.text = question
let sampleArray1 = data.array
let firstdict1 = sampleArray1![1]
print(firstdict1)
let question1 = firstdict1["question"].stringValue
self.lblQue2.text = question1
let sampleArray2 = data.array
let firstdict2 = sampleArray2![2]
print(firstdict2)
let question2 = firstdict2["question"].stringValue
self.lblQue3.text = question2
}
SVProgressHUD.dismiss()
case.failure(let error):
print(error.localizedDescription)
}
})
}
so issue is that when i am getting only two dict in response then i am getting crash on 3rd index so how to handel error please tell me i have maximum 4 question in response
how to handel error pelase some one tell me
Rather than hard-code the indices use a loop
var questions = [[String:Any]]()
if let sampleArray = data.array {
for dict in sampleArray {
print(dict)
questions.append(dict)
}
}
Or much simpler
if let sampleArray = data.array {
questions = sampleArray
}
or if you need the index
if let sampleArray = data.array {
for (index, dict) in sampleArray.enumerated() {
print(dict, index)
questions.append(dict)
}
}
You could use a switch inside a for loop to handle the different id values, this will not generate an error when array is shorter
for item in sampleArray {
if let id = item["id"] as? Int {
let question = item["question"] as? String ?? ""
switch id {
case 1:
self.lblQue1.text = question
case 2:
self.lblQue2.text = question
case 3:
self.lblQue3.text = question
case 4:
self.lblQue4.text = question
default:
print("error, unsupported id: \(id)")
}
}
}

Firebase .queryStarting not working (Swift)

This just isn't returning anything even though there are messages with timestamps above this one.
Code not properly sorting:
let messagesRef = FIRDatabase.database().reference().child("all-messages").child(messageId).queryOrdered(byChild: "timestamp").queryStarting(atValue: 1511130644)
Full code of Firebase calls:
FIRDatabase.database().reference().child("users").child(currentUserUid).child("timestampOfLastVisit").observeSingleEvent(of: .value, with: { (snapshot) in
timestamp = snapshot.value as! NSNumber
groupMessagesRef = FIRDatabase.database().reference().child("groups").child(groupId).child("messages")
groupMessagesRef.observe(.childAdded, with: { (snapshot) in
if self.sentMessage {
let messageId = snapshot.key
let messagesRef = FIRDatabase.database().reference().child("all-messages").child(messageId).queryOrdered(byChild: "timestamp").queryStarting(atValue: 1511130644)
messagesRef.observeSingleEvent(of: .value, with: { (snapshot) in ...
Relevant Firebase JSON (fake data obviously):
{
"all-messages" : {
"-KzLOuvEdLWy7vfc2XsT" : {
"fromId" : "zhBZyAVGvAMZWi4QhvKDu7qb3Qr1",
"groupId" : "-Kxk3kA9I8OEvNmFcavL",
"isStarred" : true,
"text" : "This should show",
"timestamp" : 1511130640
},
"-KzLOw5OxZ4P_I0d70gZ" : {
"fromId" : "zhBZyAVGvAMZWi4QhvKDu7qb3Qr1",
"groupId" : "-Kxk3kA9I8OEvNmFcavL",
"isStarred" : false,
"text" : "And so should this",
"timestamp" : 1511130644
},
"-KzLS4uwDtpW6wHNxrmc" : {
"fromId" : "zhBZyAVGvAMZWi4QhvKDu7qb3Qr1",
"groupId" : "-Kxk3kA9I8OEvNmFcavL",
"isStarred" : false,
"text" : "1",
"timestamp" : 1511131471
},
"-KzLS5FvASnj_ky4WQkd" : {
"fromId" : "zhBZyAVGvAMZWi4QhvKDu7qb3Qr1",
"groupId" : "-Kxk3kA9I8OEvNmFcavL",
"isStarred" : false,
"text" : "2",
"timestamp" : 1511131472
}
},
"groups" : {
"-Kxk3kA9I8OEvNmFcavL" : {
"groupCreator" : "zhBZyAVGvAMZWi4QhvKDu7qb3Qr1",
"groupDescription" : "Group",
"groupImageUrl" : "https://firebasestorage.googleapis.com/v0/b/groupchat1-a1da3.appspot.com/o/group_profile_images%2FA4DDA286-E7A3-4F96-ABF0-5717F4029C33.png?alt=media&token=6ad79728-74fd-405f-abbf-247dae4684b5",
"groupMemberOneSignalIds" : {
"5905a2f5-dfa3-46d7-964f-596bd2f2004a" : true,
"67b9cb2a-6583-45b4-9fed-93cf333e9ca4" : true,
"a1bf9ed9-0959-4c88-974b-5a829c1cdcc9" : true,
"f2fb84b9-86af-40e7-8667-989a95b2e282" : true
},
"groupMembers" : {
"3lQiuzudFGW51UwQ4Mseu8aOxyu2" : true,
"JF7SCe3VUcWJi1ujumx0VpyaG5s1" : true,
"YEbVehx0cqTvNaKrJTcs5GnRLGM2" : true,
"zhBZyAVGvAMZWi4QhvKDu7qb3Qr1" : true
},
"groupName" : "1",
"groupTags" : {
"-Kxk3kHxMuWQHEsaWN5k" : "1",
"-Kxk3kHyMB2OL5pNAfW1" : "1",
"-Kxk3kHyMB2OL5pNAfW2" : "1"
},
"messages" : {
"-KzLOuvEdLWy7vfc2XsT" : 1,
"-KzLOw5OxZ4P_I0d70gZ" : 1,
"-KzLS4uwDtpW6wHNxrmc" : 1,
"-KzLS5FvASnj_ky4WQkd" : 1
},
"starredMessages" : {
"-KzLOuvEdLWy7vfc2XsT" : 1511204335
}
},
"-Kxn_yTAZvkPls-_s8He" : {
"groupCreator" : "JF7SCe3VUcWJi1ujumx0VpyaG5s1",
"groupDescription" : "Group 3",
"groupImageUrl" : "https://firebasestorage.googleapis.com/v0/b/groupchat1-a1da3.appspot.com/o/group_profile_images%2FD2C68A8F-33DC-43C6-8C99-762315760208.png?alt=media&token=aae87339-877e-484e-a0e1-a2e13455176c",
"groupName" : "Group 3",
"groupTags" : {
"-Kxn_ygovR7mQIph3WiC" : "1",
"-Kxn_ygovR7mQIph3WiD" : "1"
}
}
},
"users" : {
"JF7SCe3VUcWJi1ujumx0VpyaG5s1" : {
"email" : "Madi#gmail.com",
"groups" : {
"-Kxk3kA9I8OEvNmFcavL" : true,
"-Kxk3n99i43MYECm1Ix8" : true,
"-KxuBPAPBIcROMEtNujW" : true,
"-KxuET1pZGg2x_aJvRkU" : true
},
"profileImageURL" : "https://firebasestorage.googleapis.com/v0/b/groupchat1-a1da3.appspot.com/o/profile_images%2F246CA55C-446D-4A24-8BE6-8B5B9C0F27AF.png?alt=media&token=47022ccd-1c92-460a-8630-e74a0d68bc4a",
"searchUsername" : "madi",
"timestampOfLastVisit" : 1511241228,
"username" : "Madi"
},
"zhBZyAVGvAMZWi4QhvKDu7qb3Qr1" : {
"email" : "Connor#gmail.com",
"groups" : {
"-Kxk3kA9I8OEvNmFcavL" : true,
"-Kxk3n99i43MYECm1Ix8" : true
},
"profileImageURL" : "https://firebasestorage.googleapis.com/v0/b/groupchat1-a1da3.appspot.com/o/profile_images%2FBDC4020E-9F54-4F80-A4DC-668804215DE3.png?alt=media&token=ec2c8875-e6e4-40d5-8c07-3d743bf4ea16",
"searchUsername" : "connor",
"timestampOfLastVisit" : 1511205356,
"username" : "Connor"
}
}
}
What print(snapshot) prints:
Snap (-KzLOw5OxZ4P_I0d70gZ) <null>
print(messageRef):
(/all-messages/-KzLOw5OxZ4P_I0d70gZ {
i = timestamp;
sp = 1511130644;
})
The goal is to create a query that will return the node that has a particular time stamp.
The problem is your code is querying one level too deep. In other words, you need to let Firebase iterate over the child nodes of all-messages until it finds one that has a child timestamp of 1511130644. So it will need to iterate over
msg_0
msg_1
msg_2
etc.
Your code is trying to be too specific and you are telling it to look at a particular message Id for the data in the query - which doesn't make sense as if you know the exact path, you wouldn't need to query!
This is a common misunderstanding - just remember that queries need to be provided the parent node and then the child node of what you are querying for as it will then iterate over the child_nodes just underneath the parent.
parent_node
child_node
child_node_of_what_you_are_querying
child_node
child_node_of_what_you_are_querying
Here is code to query for a certain time stamp - note the messageId is not needed
//self.ref is the firebase ref
let messagesRef = self.ref.child("all-messages").queryOrdered(byChild: "timestamp")
.queryStarting(atValue: 1511130644)
messagesRef.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.hasChildren() {
print("got snap with children")
} else {
print("no snap found")
}
})
If you already know the specific path you can observe it directly. So if you want to print the timestamp for a certain message
let thisMsgRef = self.ref.child("all-messages").child(messageId)
let thisTimestampRef = thisMsgRef.child("timestamp")
thisTimestampRef.observeSingleEvent(of: .value) { snapshot in
print(snap.value) //prints the timestamp
}
The second argument to queryStartingAtValue() is only used to disambiguate between items that match the first argument. To filter by timestamp you should call queryOrderedByChild("timestamp"):
let messagesRef =
FIRDatabase.database().reference().child("all-messages").child(messageId)
.queryOrdered(byChild: "timestamp")
.queryStarting(atValue: 1511130644)

Firebase check for existing user in swift

I have VC where by I am creating a new user and adding to firebase. The user inserts no problem into the database but I am having trouble checking if a user with the same name already exists. I have tried using various query statements within firebase but not getting any joy. Does anyone know how I can modify my code to accomplish this? here it is :-
#IBAction func submitUsername(sender: AnyObject) {
if let user = usernameTxtField.text where user != "" {
let username = DataService.ds.REF_USERS.childByAppendingPath("username")
username.observeSingleEventOfType(.Value, withBlock: { snap in
if let usernameDoesNotExist = snap.value as? NSNull {
let currentUser = DataService.ds.REF_USER_CURRENT.childByAppendingPath("username")
self.usernameTxtField.text = user
currentUser.setValue(user)
}
})
dismissViewControllerAnimated(true, completion: nil)
} else {
showAlert("Username Needed", msg: "please choose a username")
}
}
and the firebase data structure
"users" : {
"000591b6-ba88-4670-9cb7-edd79c273eab" : {
"newuser" : "added to FB",
"provider" : "password"
},
"05551c90-27fe-4969-b45d-279a72583857" : {
"newuser" : "added to FB",
"provider" : "password"
},
"0bbff1b0-681a-4fef-adc0-c4779a4b2100" : {
"provider" : "password",
"testing" : "emailtest",
"username" : "richy446"
},
"12f35e7a-2430-49b3-a287-f7b1daf6a121" : {
"newuser" : "added to FB",
"provider" : "password",
"username" : "richy445"
},
"15a45560-cc81-4c2d-bb59-b8ce6b125d68" : {
"provider" : "password",
"testing" : "emailtest",
"username" : "richy445"
},
"1c135936-6dd0-4189-bcd7-e8036e9736f9" : {
"newuser" : "added to FB",
"provider" : "password"
},
"21591e29-f083-452c-b74f-cc567cecb183" : {
"newuser" : "added to FB",
"provider" : "password"
},
"8b385aa7-0e80-426b-a385-5b3317c894d0" : {
"newuser" : "added to FB",
"provider" : "password",
"username" : "richy445"
}
}
There are a number of approaches to checking for duplicate data. The Firebase structure you have seems a little inconsistent so structuring it like this may be easier
"000591b6-ba88-4670-9cb7-edd79c273eab" : {
"email" : "test#test.com",
"password" : "password"
},
"05551c90-27fe-4969-b45d-279a72583857" : {
"email" : "test2#test.com",
"password" : "password"
},
1) Let Firebase do the work for you.
When creating a user, Firebase will return an error if the username (email) already exists. Using this method will prevent random data being written to your firebase until they account is created in Firebase.
myRootRef.createUser(email, password: pw, withValueCompletionBlock: { error, result in
if error != nil {
self.errMsgField.stringValue = "email/username in use, try again"
} else {
let uid = result["uid"] as! String //the uid of the new user
print("user created as \(uid)")
self.storedDataInUserNode(email, password:pw)
self.authUserWithAuthData( email, password: pw ) //auth the user
// and proceed in starting up the app
}
})
2) Checking for existing data in Firebase.
While the first method stops data from being written in the first place, if you want to check for duplicate data in general, here's a pattern:
let userName = the userName or email the user entered
let usersRef = Firebase(url:"https://test.firebaseio.com/users")
usersRef.queryOrderedByChild("email").queryEqualToValue("\(userName!)")
.observeSingleEventOfType(.Value, withBlock: { snapshot in
if ( snapshot.value is NSNull ) {
print("not found)") //didnt find it, ok to proceed
} else {
print(snapshot.value) //found it, stop!
}
}
There's a method on DataSnapshot named .exists() that you can you can call like this.
Updated for Swift 4.
struct ModelUser {
var id: String
var name: String
init(data: DataSnapshot) {
// do init stuff
}
}
func isUserRegistered(with id: String, completion: #escaping (_ exists: Bool, _ user: ModelUser?) -> ()) {
DatabaseReference.users.child(id).observeSingleEvent(of: .value) { (snapshot) in
if snapshot.exists() {
// user is already in our database
completion(true, ModelUser(data: snapshot))
} else {
// not in database
completion(false, nil)
}
}
}

Accessing son data Firebase

I have a problem, I'm trying to access some data on firebase this is the data structure
I managed to access "favorite"
This is what I used to get
ref.observeEventType(.Value, withBlock: { snapshot in
let fav = snapshot.value.objectForKey("favPost")
print("\(fav) Printed")
})
but I'm trying to access "favPost" but I couldn't figure it out?!!
Firebase structure
{
"posts" : {
"-KGIxJybfQEJbcSy2bHH" : {
"author" : "Rioodi",
"postText" : "Test",
"votes" : 1
},
"-KGIxLUmPIa1Q1k0oRLs" : {
"author" : "Rioodi",
"postText" : "Raed",
"votes" : 0
},
"-KGJe-5ciAyu6Kom98E0" : {
"author" : "Neal",
"postText" : "Neal",
"votes" : 0
},
"-KGLFC0RqW_48lHMCsx8" : {
"author" : "Rioodi",
"postText" : "Test",
"votes" : 0
}
},
"users" : {
"afd0f27a-f62f-4cf1-9e81-032edc246687" : {
"email" : "test#test.com",
"favorite" : {
"-KGIxJybfQEJbcSy2bHH" : {
"favPost" : "Test"
}
},
"provider" : "password",
"username" : "Rioodi"
},
"fc56cc22-6275-48e0-8376-0b73b273b8e2" : {
"email" : "tests#test.com",
"provider" : "password",
"username" : "Neal"
}
}
}
Since you know the userId and you also know you are looking for their favorite post, directly access it like this.
let usersRef = self.myRootRef.childByAppendingPath("users")
let thisUserRef = usersRef.childByAppendingPath("this users id")
let thisUserFavoriteRef = thisUserRef.childByAppendingPath("favorite")
thisUserFavoriteRef.observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in
let fav = snapshot.value["favPost"] as! String
print(fav)
})
you could combine the path into a single line as well
let thisUserFavoriteRef = rootRef.childByAppendingPath("users/this users id/favorite")
You can try following code. (you can change according to requirements.)
ref.observeEventType( .Value, withBlock: { snapshot in
//lets consider you have reached up to "favarites"
let favarites = snapshot?.value as! [ String : [ String : AnyObject ] ]
//In "favarites" array you will get whole list
for favarite in favarites
{
let favPost = favarite.1[ "favPost" ] as? String //to access value part
print("\(favPost) Printed"
}
}

Resources