Firebase sort query gives (unsorted) dictionary results - ios

So I'm sure I'm missing something here, but when I wish to do a query for, say, the top 10 scores in a certain game, Firebase returns the top 10 scores, however since they are then gives back as a dictionary (key generated with childByAutoId), they are 'unsorted' when received on the client side (so to display a top 10 you have to sort them again)...
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
FIRDatabaseQuery *jungleHighscoresQuery = [[[ref child:#"jungleScores"] queryOrderedByChild:#"score"] queryLimitedToLast:4];
[jungleHighscoresQuery observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot){
NSDictionary *postDict = snapshot.value;
NSLog(#"%#", postDict);
}];
The above code gives the following output (these are the top 4 scores among the ~20 in the database):
{
"-KIUhe_9TLQoy_zNbJT0" = {
score = 290;
userid = oMqoPGJYsGWHffYx8N6vDk3Osh72;
};
"-KIUj8VUyNMgyZ135dI_" = {
score = 560;
userid = oMqoPGJYsGWHffYx8N6vDk3Osh72;
};
"-KIUjK15Gy9PRB_JBWOA" = {
score = 240;
userid = oMqoPGJYsGWHffYx8N6vDk3Osh72;
};
"-KIUlZ1a03r7bjPYNueG" = {
score = 740;
userid = oMqoPGJYsGWHffYx8N6vDk3Osh72;
};
}
I know it's an easy task to just sort it all again, but it seems weird to have to do.

There was an easy solution after all, just had to grab the enumerator instead of the dictionary:
NSEnumerator *enumerator = snapshot.children;
and then just iterate through them with [enumerator nextObject]

Related

Firebase database query by key value

I have JSON like this.
livefeeds= {
"-KTn8pbqFHBUvgJ1Gwyl" = {
category = Alerts;
text = "Samsung Galaxy Note 7 owners told to turn off device";
timestamp = 1476179485648;
"user_id" = V7EFBV6uATf8urLXX9eK4EHhxmG2;
};
"-KTn8pbrhHyNzeLh2vOq" = {
category = News;
text = "Chicago Teachers Union, school board reach tentative contract agreement";
timestamp = 1476179485648;
"user_id" = V7EFBV6uATf8urLXX9eK4EHhxmG2;
};
}
I need to make query based on the key category.
Ex: If I only want Alerts, it should only retrieve category value equal to "Alerts" data only.
Here is query to retrieve livefeeds.
[[self.ref queryOrderedByChild:#"livefeeds"] observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
NSLog(#"---> %#",snapshot.value);
}];
First go till child "livefeeds" and then "queryOrderedByChild" category and use equal to child like this way
[[[[self.ref child:#"livefeeds"] queryOrderedByChild:#"category"]
queryEqualToValue:groupId]
observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
if (snapshot.value != [NSNull null]){
for (NSDictionary *snap in [snapshot.value allValues]) {
NSLog(#"---> %#",snap);
}
}
}];

Parsing JSON with NSDictionary

I am working on an app which fetches data from a server. I convert this data to XML and then parse it using XMLDictionary. My problem is counting the number of objects inside the dictionary.
"finance_fee_collection" = (
{
amount = "790.00";
"due_date" = "2015-06-04";
name = "Third Payment";
},
{
amount = "790.00";
"due_date" = "2014-12-11";
name = "First Payment";
},
{
amount = "740.00";
"due_date" = "2015-07-06";
name = "third payment";
}
);
Counting the above number of objects yields 3, which is true. But counting the following also results 3.
"finance_fee_collection" = {
amount = "740.00";
"due_date" = "2015-07-06";
name = "third payment";
};
What I want is to count the number of "finance_fee_collection" items, such that the first one results 3 and the second one results 1. Is there anyway I can approach this goal?
The first one seems to be an array, the second a dictionary:
if([finance_fee_collection iskindOfClass:[NSDictionary class]]){
count = 1;
} else {
count = result.count;
}
something similar to this should work. :) hope it is helpful.
This doesn't make sense really, since both NSArray and NSDictionary implement the count method, which should return 3 for both structures:
id obj = #[#1 ,#2, #3]; // This is an NSArray
NSLog(#"%lu", (unsigned long)[obj count]); // Outputs 3
obj = #{ #1:#1,
#2:#2,
#3:#3
}; // now it's an NSDictionary
NSLog(#"%lu", (unsigned long)[obj count]); // Outputs 3
Were you using [object count] to get the count?
Either way, I wouldn't assume that count would be 1 simply because the data structure is a dictionary (you didn't count it)

Retrieve 1 specific key from several NSArrays and add them together

In my app, I am needing to loop through each NSArray, get the NSInteger associated with the key 'people' in the NSArray, and then add them all together. What would be a good starting point for first retrieving each specific NSInteger from each NSArray?
The array in question returns like this in console.
(
"<Prayers:DDomBXIONY:(null)> {\n Anonymous = 1;\n DeviceID = 123;\n FirstName = Name;\n LastName = Name;\n Location = HI;\n PrayerWarriors = 8;\n Request = Hi;\n Title = Hi;\n UserId = RtXN6QZsgaIiPw4SjFWGtkxXx;\n dateMade = \"Jan_09_2015\";\n}"
)
Basically just need to retrieve NSInteger from each PrayerWarriors key, and add them all together.
(
"<Prayers:DDomBXIONY:(null)> {\n Anonymous = 1;\n DeviceID = 123;\n FirstName = Name;\n LastName = Name;\n Location = HI;\n PrayerWarriors = 8;\n Request = Hi;\n Title = Hi;\n UserId = RtXN6QZsgaIiPw4SjFWGtkxXx;\n dateMade = \"Jan_09_2015\";\n}",
"<Prayers:yG7GC4bCIH:(null)> {\n Anonymous = 1;\n DeviceID = 123;\n FirstName = Name;\n LastName = Name;\n Location = bye;\n PrayerWarriors = 0;\n Request = bye;\n Title = bye;\n UserId = RtXN6QZsgaIiPw4SjFWGtkxXx;\n dateMade = \"Jan_09_2015\";\n}"
)
So without understanding exactly how your PFObject works, I'm going to assume it's like a dictionary.
Add each of your objects to a single array:
NSMutableArray *arrayHoldingPrayersObjects = [NSMutableArray alloc] init];
arrayHoldingPrayersObjects[0] = prayerObject1;
arrayHoldingPrayersObjects[1] = prayerObject2;
arrayHoldingPrayersObjects[2] = prayerObject3;
etc...
Then create a integer variable outside of a for loop and iterate through your objects, adding the value for PrayerWarrior at each iteration.
int totalPrayerWarriors = 0;
for (int i = 0; i < arrayHoldingPrayersObjects.count; i++)
{
NSMutableDictionary *prayerObject = arrayHoldingPrayersObjects[i];
totalPrayerWarriors += [prayerObject objectForKey:#"PrayerWarriors"] intValue];
}
You should end up with a correct total from all arrays. Do some tests to make sure it's accurate for you. Hope this helps.
*EDIT
The error you're getting indicates that it actually is a NSMutableArray, which you can't access using methods like objectForKey, so... there must be a method provided by PFObject that allows you to do that. OR, if PrayerWarriors is reliably the [5]th value (including 0) in the array, then you might be able to access it by index.
replace the lines:
NSMutableDictionary *prayerObject = arrayHoldingPrayersObjects[i];
totalPrayerWarriors += [prayerObject objectForKey:#"PrayerWarriors"] intValue];
with
NSMutableArray *prayerObject = arrayHoldingPrayersObjects[i];
totalPrayerWarriors += prayerObject[5];
Not sure where the mutable array is coming from. Parse.com will always produce immutable arrays as far as I know. So lets say you've retrieved Prayers with:
PFQuery *query = [PFQuery queryWithClassName:#"Prayers"];
[query findObjectsInBackgroundWithBlock:^(NSArray *prayers, NSError *error) {
// see how it's an NSArray, not mutable
}];
Now you want the total of the retrieved PrayerWarrior attributes, so...
[query findObjectsInBackgroundWithBlock:^(NSArray *prayers, NSError *error) {
NSInteger total = 0;
for (PFObject *p in prayers) {
NSNumber *warriorCount = p[#"PrayerWarriors"];
total += [warriorCount intValue]; // notice we cannot add nsnumbers directly (we need intValue)
}
NSLog(#"total warriors = %d", total);
}];

Group NSDictionary by dates [duplicate]

This question already has answers here:
Grouping NSArray of NSDictionary based on a key in NSDictionay
(2 answers)
Closed 8 years ago.
I have a NSDictionary and i want to group it creating an array of objects by date
Example of the main NSDictionary:
({
date = "2014-04-27";
group = "yellow.png";
length = 180;
},
{
date = "2014-04-28";
group = "blue.png";
length = 180;
},
{
date = "2014-04-27";
group = "blue.png";
length = 120;
})
I want to group something similar as:
2014-04-27 = (
{
date = "2014-04-27";
group = "yellow.png";
length = 180;
},
{
date = "2014-04-27";
group = "blue.png";
length = 180;
})
2014-04-28 = ( {
date = "2014-04-28";
group = "blue.png";
length = 120;
})
Could someone help me? i have tried many FOR but i cant get it
It appears as though your original data structure is an array of dictionaries. Was your question phrased incorrectly? I see each individual dictionary but they are not keyed on anything in the top level data structure.
Assuming that is the case (you have an array called originalArray
NSMutableDictionary *dictionaryByDate = [NSMutableDictionary new];
for(NSDictionary *dictionary in originalArray)
{
NSString *dateString = dictionary[#"date"];
NSMutableArray *arrayWithSameDate = dictionaryByDate[dateString];
if(! arrayWithSameDate)
{
arrayWithSameDate = [NSMutableArray new];
dictionaryByDate[dateString] = arrayWithSameDate;
}
[arrayWithSameDate addObject: dictionary];
}
By the end of this, dictionaryByDate will be a dictionary (keyed on date) of arrays (all objects in a given array will be dictionaries with the same date).

Parsing json returned by foursquare for iPhone gives Unrecognised leading character

I'm trying to get the nearby places using the foursquare api.
Here's the json data that is returned from
NSDictionary *results = [jsonString JSONValue];
NSLog(#"%#", results);
(
{
code = 200;
errorDetail = "This endpoint will stop returning groups in the future. Please use a current version, see http://bit.ly/lZx3NU.";
errorType = deprecated;
},
{
groups = (
{
items = (
{
categories = (
{
icon = "https://foursquare.com/img/categories/parks_outdoors/default.png";
id = 4bf58dd8d48988d163941735;
name = Park;
parents = (
"Great Outdoors"
);
pluralName = Parks;
primary = 1;
shortName = Park;
}
);
Then I try to get the list of the groups in an array with
NSArray *groups = [ (NSDictionary *)results objectForKey:#"groups"];
This returns the following error
2011-11-05 11:42:12.907 XperienzApp[1972:207] No of results returned: 0 Results : (null)
2011-11-05 11:42:13.225 XperienzApp[1972:207] -JSONValue failed. Error trace is: (
"Error Domain=org.brautaset.JSON.ErrorDomain Code=3 \"Unrecognised leading character\" UserInfo=0x5849cd0 {NSLocalizedDescription=Unrecognised leading character}"
)
2011-11-05 11:42:13.225 XperienzApp[1972:207] No of results returned: 0 Results : (null)
How should I parse this?
Edit:
I tried the suggested technique, this gives me an array
id groups = [[(NSDictionary *)results objectForKey:#"response"] objectForKey:#"groups"];
if ([results count] > 1){
NSLog(#"groups class %#\ngroups %# %d", groups, [groups class], [groups count]);
The log output is of the form:
{
categories = (
{
icon = "https://foursquare.com/img/categories/nightlife/danceparty.png";
id = 4bf58dd8d48988d11f941735;
name = Nightclub;
parents = (
"Nightlife Spots"
);
pluralName = Nightclubs;
primary = 1;
shortName = Nightclub;
}
);
contact = {
};
hereNow = {
count = 0;
};
id = 4eb33ba561af0dda8f673c1b;
location = {
address = "144 Willow St 4R";
city = Brooklyn;
crossStreet = Pierrepont;
distance = 462;
lat = "40.696864";
lng = "-73.996409";
postalCode = 11201;
state = NY;
};
name = "Entertainment 720, Ltd.";
stats = {
checkinsCount = 3;
tipCount = 0;
usersCount = 1;
};
verified = 0;
}
);
name = Nearby;
type = nearby;
}
)
groups __NSArrayM 1
This is again not json and is hard to parse, how do I get the output in json.
I'm the iPhone lead at foursquare. I'll try to take a stab at what's going on here.
First of all, I highly recommend you use JSONKit for your parser. It's lightweight and insanely fast: https://github.com/johnezang/JSONKit
It appears that you are parsing the JSON properly and getting the dictionary properly. Then you are logging the parsed object, not the original JSON. The output you are seeing is how Objective-C chooses to serialize the parsed dictionary to text. It is definitely not JSON. Using JSONKit, you could send the JSONString selector to your parsed result and convert it back to JSON and log that.
If you could provide some details on the problem you are trying to solve, I might be able to help you out more. And as Maudicus said, please pay attention to the error you are getting back. You don't want your app to break when we make the change to the API.
If the output below NSLog(#"%#", results); is your log statement. It appears your results variable is an array of dictionary objects.
Try to log the class of results to verify that NSLog(#"%#", [results class]);
If it is an array your groups object is the second object.
if ([results count] > 1)
id groups = [results objectAtIndex:1];
NSLog(#"groups class %#\ngroups %#", [groups class], groups);
Keep doing this until you understand the format of your data
Also the line
errorDetail = "This endpoint will stop returning groups in the future. Please use a current version, see http://bit.ly/lZx3NU.";
should be cause for concern. Check the documentation on foursquare for the current way of getting groups.

Resources