Trouble trying to retrieve data from Firebase - swift

I have this piece of working code that saves data to Firebase:
let locRef = locationRef.childByAutoId()
let locItem = [
senderId : [
"location": getLocationID()
]
]
locRef.setValue(locItem)
And I want to retrieve the user's (identified by senderID) "location", so I tried this piece of code:
locationRef.child("location").child(senderId).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
self.locationId = snapshot.value!["location"] as! String
}) { (error) in
print(error.localizedDescription)
}
However my app is crashing when the piece of code is run, and there are no errors. I think my mistake may be that .child("location") must be something else, but I do not know what.
Database structure (JSON):
{
"locations" : {
"-KLEdoj2eiF7EW9m0815" : {
"W6vSOHZLTwNM33JYqkKHvaIVRF13" : {
"location" : "Seattle, WA"
}
},
"-KLLfcOvYHwIufBALM0-" : {
"W6vSOHZLTwNM33JYqkKHvaIVRF13" : {
"location" : "London, United Kingdom"
}
},
Any help would be appreciated thanks!

You should be referring to your location as the following
FIRDatabase.database().reference().child("locations").child(locationId).child(senderId).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
self.location = snapshot.value!["location"] as! String
}
For example:
If you have locationId = "-KLEdoj2eiF7EW9m0815" and senderId = "W6vSOHZLTwNM33JYqkKHvaIVRF13" the above call will set the self.location to "Seattle, WA"

Related

Counting Records In Swift From Firebase With A Where Statement

I am trying to return the count of posts for a specific user where a field contains a certain value. The structure I am using in Firebase is here:
{
"posts" : {
"-Lyzpsb1hH4LUPvcXE3H" : {
"beverageCategory" : "Beer",
"beverageName" : "Dortmunder",
"beveragePrice" : "3.99",
"beverageRating" : 3,
"beverageType" : "Lager",
"imageUrl" : "https://firebasestorage.googleapis.com/v0/b/socialspirit-37cae.appspot.com/o/post-pics%2F3C23E923-A3BD-4393-B3EF-8F939D8B08B8?alt=media&token=ac80cb98-f2a1-4197-b328-2a69a2ac1fd1",
"wineVintage" : ""
}
},
"user" : "sdkjvksdjf",
"users" : {
"0hyN8N2klJWqPi2lkRqNK3vg7z63" : {
"posts" : {
"-Ly6ciYHm7v5JFy1VmVY" : true,
"-Ly6cyLukI6aRRki5yna" : true
},
"provider" : "Firebase"
},
"26OUuaRZEVWUmkLJp13LzirGbs13" : {
"posts" : {
"-Ly6fGmQEMZz3c-azMnJ" : true
},
"provider" : "Firebase"
},
"5r6FulsvIRap7pLK5D3zV8qyPVv1" : {
"provider" : "Firebase"
},
"gQpktBMh97hTqiysHBwvVLZl70y1" : {
"posts" : {
"-Lyzpsb1hH4LUPvcXE3H" : true,
"-LyzqFgvmrBgdsgKSt_5" : true,
"-Lz-fIMDal00ex3_viQo" : true,
"-Lz-lXsSBqKlcf8hBext" : true,
"-Lz2eNLfk1PFEVkEgmwa" : true,
"-Lz2etF0UqFqLkdGOR13" : true,
"-Lz2fGUi0qzJtniNr5LX" : true,
"-Lz2gP5c47yHDO2g0ljr" : true,
"-Lz2gdhfedZfTtzjP2ee" : true,
"-Lz2gllC3caXgPf2VAPU" : true,
"-Lz2hH8FbNmBEOLcHCJz" : true,
"-Lz2jzkXuEZ3Cfe96eGW" : true,
"-Lz3RvuW4fMXarhW7vLv" : true,
"-Lz3S8YA0vgk4ZrjL_Kk" : true
},
"provider" : "Firebase"
}
}
}
I am using the following code to get the count of records that have a beverageCategory of "Beer".
DataService.ds.REF_USERS.child("\(uid)").child("posts").child("beverageCategory")
.queryOrderedByValue().queryEqual(toValue: "Beer")
.observe(DataEventType.value, with: { (snapshot) in
print("SNAP - \(snapshot.childrenCount)")
})
The childrenCount returns 0, however. Any idea what I'm doing wrong here? Thanks!
EDIT: I added the JSON for the data structure and I think I left an important detail out. The data structure actually has users that have posts and the associated postid that links back to posts. I think what I have to do is first find the user's posts and then of those posts get a total count for each category. I'm guessing that is slightly different than the methods I tried. Any ideas on that?
EDIT 2: So my issues is that users and posts are in different structures. I need to find all of the user's posts and iterate through them to see if what the beverageCategory is. I have done that with the following code. The issue with the code below is that the count is doubled when I add a post and then open the menu. But when I exit the menu and re-open the count is correct. Why is it double-counting?
func myFirebaseNetworkDataRequest(finished: #escaping () -> Void) {
beerCountArray.removeAll()
wineCountArray.removeAll()
liquorCountArray.removeAll()
print("BEER ARRAY \(beerCountArray.count)")
guard let uid = Auth.auth().currentUser?.uid else {
return
}
let newPost = DataService.ds.REF_USERS.child("\(uid)").child("posts")
newPost.observe(.value, with: { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
//print("SNAPSHOT - \(snapshot)")
for snap in snapshot {
let postData = DataService.ds.REF_POSTS.child(snap.key)
//print("SNAP KEY - \(snap.key)")
let bevCat = DataService.ds.REF_POSTS.child(snap.key).child("beverageCategory")
//print("BEV CAT - \(bevCat)")
postData.observe(.value, with: { (snapshot) in
if let postDict = snapshot.value as? Dictionary<String, AnyObject> {
let key = snapshot.key
let post = Post(postKey: key, postData: postDict)
//print("POST DICT - \(String(describing: postDict["beverageCategory"]!))")
if postDict["beverageCategory"]! as! String == "Beer" {
self.beerCountArray.append(1)
//print("BEER ARRAY LOOP - \(self.beerCountArray)")
}
if postDict["beverageCategory"]! as! String == "Wine"{
self.wineCountArray.append(1)
}
if postDict["beverageCategory"]! as! String == "Liquor" {
self.liquorCountArray.append(1)
}
//self.posts.append(post)
}
finished()
})
}
}
})
}
And...
override func viewDidLoad() {
super.viewDidLoad()
beerCountArray.removeAll()
wineCountArray.removeAll()
liquorCountArray.removeAll()
myFirebaseNetworkDataRequest {
//print("BEER ARRAY - \(self.beerCountArray.count)")
self.beerCount.text = String(self.beerCountArray.count)
self.liquorCount.text = String(self.liquorCountArray.count)
self.wineCount.text = String(self.wineCountArray.count)
}
}
Your query is not correct. Since you're trying to filter on a child property of each node under posts, you should call queryOrdered(byChild:).
So:
DataService.ds.REF_USERS.child("posts")
.queryOrdered(byChild: "beverageCategory")
.queryEqual(toValue: "Beer")
.observe(DataEventType.value, with: { (snapshot) in
print("SNAP - \(snapshot.childrenCount)")
})
Also see the Firebase documentation on ordering and filtering data.

Fetch all relationship data - Core Data

I am new to core data. I am fetching data from API and then saving them to core data.This is my dataModel.
Here is my API Structure,
{
"name" : "name here",
"content" :[
{
"homeContentItems" : [
{
"some objects" : "values",
"contentItemDetails": [
{
},
{
}
]
},
{
"some objects" : "values",
"contentItemDetails": [
{
},
{
}
]
}
]
},
{
"homeContentItems" : [
{
"some objects" : "values",
"contentItemDetails": [
{
},
{
}
]
},
{
"some objects" : "values",
"contentItemDetails": [
{
},
{
}
]
}
]
}
]
}
How can I fetch data from the Entity so I can get all data from related entity too?
I Have never worked with database before so its bit complected for me. Any help will be much appreciated.
let informedDataFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Informed360Entity")
informedDataFetch.fetchLimit = 1
informedDataFetch.predicate = NSPredicate()
let tableviewData = try! context.fetch(informedDataFetch)
let tdata : Informed360Entity = tableviewData.first as! Informed360Entity
var contentData = tdata.toContent?.allObjects as? [ContentEntity]
I tried this code and getting data from ContentEntity table. How can I get other 2 tables data too so I can use to display in tableview.
You do it the same way as you did with ContentEntity but now you use the two properties that represent the relationships, contentDetailItem and homeContentItems, which both will return a Set.
for content in contentData {
let contentDetailItems = content.contentDetailItem
let homeContents = content.homeContentItems
//...
}

Is it possible to get database reference without childByAutoId (). Key?

Is there a way to dynamically get a child database from the parent instance, without having to use childByAutoId () ?
{
"artists" : {
"artists_id_1" : {
"name" : "Atif Aslam",
"genre" : "Rock"
},
"artists_id_2" : {
"name" : "Arijit Singh",
"genre" : "Rock"
}
}
}
we usually refer to the path, and listener the items the DataBase...Example:
Database.database().reference().child("artists").child("artist_id_1").observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
print("\(String(describing: dictionary["name"] as? String))")
}
}, withCancel: nil)
it would only work for the first item. Because, it would not be dynamic. What is normally used is the following example below ...
{
"artists" : {
"-KeZUDrJv555kteAcssL-" : {
"name" : "Atif Aslam",
"genre" : "Rock"
},
"-KeZUVXFIQdO7JiyRYk-" : {
"name" : "Arijit Singh",
"genre" : "Rock"
}
}
}
Database.database().reference().child("artists").childByAutoId().observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
print("\(String(describing: dictionary["name"] as? String))")
}
}, withCancel: nil)
Anyway, I do not know if it was clear, anything can comment before answering. Thank you
To display all artists in your database, load the artists node and loop over snapshot.children:
Database.database().reference().child("artists").observe(.value) { (snap:DataSnapshot) in
for child in snapshot.children {
print(child.key)
}
}
For this and more examples, I recommend reading the Firebase documentation, specifically the section on reading and writing lists.
I dont know if i understand your question correctly or what you are trying to do but maybe you can try
Database.database().reference().child("artists").observe(.value) { (snap:DataSnapshot) in
// This should print out your childIds
print(snap.key)
// This should print out the values after them
print(snap.value)
}

How retrieve coordinates in same order?

"-KHbCuQflKHrJiUmfpG0" : {
"coordinates" : {
"-KHbCuQflKHrJiUmfpG1" : {
"latitude" : 13.17078652595298,
"longitude" : -59.5775944578738
},
"-KHbCuQflKHrJiUmfpG2" : {
"latitude" : 13.15541190861343,
"longitude" : -59.57619643155932
},
"-KHbCuQg9W_tebl1pU66" : {
"latitude" : 13.148444967591,
"longitude" : -59.5589266947333
}
},
"subtitle" : "patrick",
"title" : "River",
"type" : "polyline"
},
This is my JSON structure for saving polylines and I need retrieve coordinates in same order.
This is my code for obtaining coordinates and creating polylines.
// geoobject.key - is ID of geoobject (for loop geoobjects) "-KHbCuQflKHrJiUmfpG0"
DataService.dataService.getGeoObject(geoobject.key).observeEventType(.Value, withBlock: { geoSnapshot in
var coordinatesPolyline = [CLLocationCoordinate2D]()
if let geoDictionary = geoSnapshot.value as? Dictionary<String, AnyObject> {
let id = geoSnapshot.key
if geoDictionary["type"] as! String == "polyline" {
if let coords = geoDictionary["coordinates"] as? [String:[String:Double]] {
let contents = coords.values
for content in contents {
let latitude = content["latitude"]
let longitude = content["longitude"]
let point = CLLocationCoordinate2D(latitude: latitude!, longitude: longitude!)
coordinatesPolyline.append(point)
}
// coordintesPolyline contains shuffle coordinates
let polyline = Polyline(coordinates: &coordinatesPolyline, count: coordinatesPolyline.count)
//coordinates = []
polyline.id = geoSnapshot.key
polyline.title = geoDictionary["title"] as? String
polyline.subtitle = geoDictionary["subtitle"] as? String
self.polylines.insert(polyline, atIndex: 0)
}
}
})
I rendered polylines but polylines are renderder bad because coordinates are shuffle.
Does anyone know how to get coordinates in the correct order. Firebase retrieve coordinates shuffle and then rendering doesn't work well.
Thank you for some advice.
When reading firebase data by .Value, ALL of the data within the node is returned in the snapshot.
If you want the data in a specific order, you need to decide what 'thing' you want it ordered by. The natural order is by key, but if you want it ordered by some other parameter, you need to include that in you firebase structure, and then add orderedBy to your observe.
One you have the data by .Value, you then need to iterate over each child within the snapshot to access that nodes data. For example
If your Firbase structure is
"coordinates" : {
"-KHbCuQflKHrJiUmfpG1" : {
"latitude" : 13.17078652595298,
"longitude" : -59.5775944578738
},
"-KHbCuQflKHrJiUmfpG2" : {
"latitude" : 13.15541190861343,
"longitude" : -59.57619643155932
},
"-KHbCuQg9W_tebl1pU66" : {
"latitude" : 13.148444967591,
"longitude" : -59.5589266947333
}
Then the snapshot contains All of that data. Iterate over the snapshot and work with each child:
ref.observeEventType(.Value, withBlock: { geoSnapshot in
for child in geoSnapshot.children {
let lat = child["latitude"] as? String
let long = child["longitude"] as? String
print("lat = \(lat) long = \(long)"
}
})
(didn't test that code but it's close)
Oh, and one other thing. ObserveEventOfType(.Value) will continually observe the node for changes - add, change or remove and will fire any time one of those events occur.
If you just want a one-shot, use ObserveSingleEventOfType(.Value)

Swift & Firebase | Checking if a user exists with a username

I am trying to allow users to start games with and follow other users by searching their username. I need to be able to make sure that a user with that username exists. I was using the following code but although the if is called the else does not get called when it should.
let checkWaitingRef = Firebase(url:"https://test.firebaseio.com/users")
checkWaitingRef.queryOrderedByChild("username").queryEqualToValue("\(username!)")
.observeEventType(.ChildAdded, withBlock: { snapshot in
if snapshot.value.valueForKey("username")! as! String == username! {
} else {
}
JSON data tree
{
"097ca4a4-563f-4867ghj0-6209288bd7f02" : {
"email" : "test1#tes1.com",
"uid" : "097ca4a4-563f-4867ghj0-6209288bd7f02",
"username" : "test1",
"waiting" : "0"
},
"55a8f979-ad0d-438u989u69-aa4a-45adb16175e7" : {
"email" : "test2#test2.com",
"uid" : "55a8f979-ad0d-438u989u69-aa4a-45adb16175e7",
"username" : "test2",
"waiting" : "0"
}
}
Easy fix:
Don't use .childAdded as the block will not execute when the query doesn't find anything.
Instead use .Value and check for NSNull
let checkWaitingRef = Firebase(url:"https://test.firebaseio.com/users")
checkWaitingRef.queryOrderedByChild("username").queryEqualToValue("\(username!)")
.observeEventType(.Value, withBlock: { snapshot in
if ( snapshot.value is NSNull ) {
print("not found)")
} else {
print(snapshot.value)
}
})