Working with fetched request sort descriptors - objective-c

I have problem with my sort descriptor. I am fetching a ranking of a football club. This is how my webservice gives the data back.
"ranking": [
{
"type": "competitie",
"position": "1",
"name": "Club Brugge",
"gamesPlayed": "10",
"gamesWon": "6",
"gamesTied": "4",
"gamesLost": "0",
"goalsPos": "25",
"goalsNeg": "12",
"goalsDiff": 13,
"points": "22"
}
Here is my fetch request.
- (void)getKlassement // attaches an NSFetchRequest to this UITableViewController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Klassement"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"position" ascending:YES]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.genkDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
Now the ranking is the following. 1,11,12,13,14,2,3,4,5...
I think the problem is that position is a String in my webservice. And my sort descriptor is looking at it as a string. But actually it should look at it as an integer. Does anybody knows how I can do this ?
Thanks in advance.

Even if the "position" is provided as a string from your web service, the best solution would be to store it as number ("Integer 32" or similar) in the Core Data model. The corresponding property of the object will be NSNumber and it will be sorted correctly.
If you really cannot go this way, you could as a workaround try to use localizedStandardCompare as comparison function. I think that sorts strings containing numbers according to their numeric values.
[NSSortDescriptor sortDescriptorWithKey:#"position" ascending:YES
selector:#selector(localizedStandardCompare:)]

Related

iOS and JSON nesting issue

I am working on an app for a game server company and part of the app requires the user to see a list of his or her game servers and whether or not they are online, offline, how many players on them, the server name, etc. This data is all found in a JSON file hosted on the web updated from a MySQL database.
Using the code below, I can't seem to get it working. Now, please understand it is one of my first times working with JSON and have no choice as this is what the client requested. I talked to my partner but he couldn't seem to debug the issue himself.
The error I get is something like:
No visible #interface for 'NSArray' declares the selector 'objectForKey:'
I've tried several versions of the code, all with no success.
It would be much appreciated if you could please help me debug this code and get it working along with the commented out section near the bottom updating the TableViewCells with the server name, players online, and status (0=offline, 1=online, 2=busy, 3=suspended, -1=unable to start).
Please note that the format of the JSON file must remain as is and is only possible to make very minor changes.
Thank you,
Michael S.
My header file:
http://pastebin.com/EkuwVSmY
My main file:
http://pastebin.com/09Ju0uDu
My JSON file:
{
"status": "OK",
"error": "",
"debug": "2 server(s)",
"result": {
"servers": [
{
"id": 1,
"title": "Test",
"players": 0,
"slots": 10,
"status": 3
},
{
"id": 2,
"title": "Creative Spawn",
"players": 0,
"slots": 5,
"status": -1
}
]
}
}
The block that gives me the error is:
NSArray *serverResults = [[news objectForKey:#"result"] objectForKey:#"servers"];
if ([[[serverResults objectAtIndex:indexPath.row] objectForKey:#"status"] isEqual:#"1"]) {
serverPlayers.text = #"10000000";
}
The error you get points out that you are working on an NSArray instead of a NSDictionary. There is no method objectForKey defined on an NSArray. So what you could do is to debug your Webservice response and check the Data types.
Regarding at your output from JSON it should be like that:
NSDictionary (Keys: status, error, debug, result, servers)
servers is an NSArray which has NSDictionaries as elements.
To get the title of a server:
NSDictionary *resultDict = [news objectForKey:#"result"];
NSArray *servers = [resultDict objectForKey:#"servers"];
NSDictionary *firstServer = [servers objectAtIndex:0]; // I fetch here the first server
NSString *titleOfFirstServer = [firstServer objectForKey:#"title"];
NSNumber *statusOfFirstServer = [NSNumber numberWithInt:[[firstServer objectForKey:#"status"] intValue];
To iterate over all servers you should do it like that:
NSDictionary *resultDict = [news objectForKey:#"result"];
NSArray *servers = [resultDict objectForKey:#"servers"];
for(NSDictionary *server in servers) {
NSString *title = [server objectForKey:#"title"];
NSNumber *status = [NSNumber numberWithInt:[[server objectForKey:#"status"] intValue];
NSLog(#"%#%d", title, [status intValue]);
}

How to fetch an array of attributes in iOS Core Data?

I'm using CoreData (NSManagedObject, UIManagedDocument) for an iOS app and I was wondering if it is possible to fetch an array of attributes.
For example, suppose I have Person entities in my database and each Person has an attribute called income and a name called name. Suppose I have multiple Persons in my database. Is it possible to fetch an array containing all of the incomes for my entire database? (An array with each person's income as an entry). If so, how would I sort the array by their name?
If this is not possible, how would you suggest I go about accomplishing this? I don't want to fetch the entire Person entity because there are many other large attributes such as images which would take a long time to fetch.
You can fetch the properties you want this way:
NSFetchRequest* fetchRequest = [NSFetchRequest new];
fetchRequest.entity = <person entity description>;
fetchRequest.propertiesToFetch = #[ #"name", #"income" ];
fetchRequest.sortDescriptors = #[ [NSSortDescriptor sortDescriptorWithKey: #"name" ascending: YES] ];
fetchRequest.resultType = NSDictionaryResultType;
NSError* error = nil;
NSArray* personsAttributes = [managedObjectContext executeFetchRequest: fetchRequest error: &error];
personsAttributes will look like that:
[
{ "name" : "Alfred", "income" : 1000 },
{ "name" : "Birgite", "income" : 2000 },
…
]
Code with ARC & literals. You'll may have to tailor it to your needs and compilation options.

Can't parse JSON from data in connectionDidFinishLoading – Maybe it's too much data?

I'm sending out a request to an external API and parsing a response with the SBJson parser. However, I suspect the response is so long, it is somehow getting jumbled.
In my mainviewcontroller.h file I set NSMutableData *receivedData; so that I can use it in the connection methods in the mainviewcontroller.m file.
However, after the connection finishes loading, I execute the following:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *dataString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
NSArray *allData = [dataString JSONValue];
}
However, I get a bunch of errors saying that the JSON is not properly formatted. So, when I look at the JSON, its very long – but here and there, there are problems... for example, the "updated_at" below.
{
"id": 7844333,
"position": 3,
"content": "Cell height is off by 5 pixels",
"created_at": "2012-06-04T20:31:30-05:00",
"updated_at": "2ator": {
"id": 98258,
"name": "Brian"
}
What I think happened above is that updated at has a value of "2012-06...etc" and the next key-value item would be creator : { id, name } but it somehow got jumbled into updated at.
Anyone having a similar problem? I don't think the problem is with the JSONValue because I nslog out the dataString before it gets parsed, and thats where I find the JSON errors.
What I mean by that is that NSString *dataString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding]; is just a long string, but has bad JSON in it because it is jumbled.
Are you using receivedData by more than one connection at once?
:)
I think your json is wrong. For checking that just put json file into the :
http://jsonlint.com/
If it is valid then:
Import the SBJSON framework classes into your project.And try the following code:
SBJSON *parser=[[SBJSON alloc]init];
NSDictionary * dictionary = [parser objectWithString:responseString];
this will give you data into dictionary then by using:
NSString *firstParseData=[dictionary objectForKey:#"your key"];
you can retrieve the data. Hope this will work in your case.

Objective - C : How to read json? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to parse JSON in Objective-C?
I totally new with Objective c, I need to value of distance from google distance matrix json, but data that I can get from json just the first element,
so How to get value in distance this json?
{
"destination_addresses": [
"San Francisco, Californie, États-Unis",
"Victoria, BC, Canada"
],
"origin_addresses": [
"Vancouver, BC, Canada",
"Seattle, État de Washington, États-Unis"
],
"rows": [
{
"elements": [
{
"distance": {
"text": "1 732 km",
"value": 1732128
},
"duration": {
"text": "3 jours 23 heures",
"value": 340902
},
"status": "OK"
}
]
}
],
"status": "OK"
}
ok here is my sample code that just follow from JSON Tutorial :
I already use SBJSON , but I can only rows key, so how to get value in Distance key?
SBJSON *parser = [[SBJSON alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL
URLWithString:#"http://maps.googleapis.com/maps/api/distancematrix/json?origins=Vancouver+BC|Seattle&destinations=San+Francisco|Victoria+BC&mode=bicycling&language=fr-FR&sensor=false"]];
// Perform request and get JSON back as a NSData object
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSArray *statuses = [parser objectWithString:json_string error:nil];
for (NSDictionary *status in statuses)
{
NSLog(#"%# - %#", [status objectForKey:#"rows"]);
}
If you're targeting iOS 5 or OS X v10.7 then you can just use Apple's own NSJSONSerialization. You probably particularly want +JSONObjectWithData:options:error:. Using the built-in stuff is always preferable to third-party options because it eliminates the problem that the third party has no direct interest in fixing its bugs and no way to supply fixes for your application without your intervention.
If you want to support older devices then you probably want to import SBJSON — as as Rengers suggests — or any of the hundred others. For the reasons above I highly recommend you fall back on those only if NSJSONSerialization isn't available.
EDIT: it appears you already have SBJSON in place and are asking about how to traverse the results? From reading the JSON:
the root object will be a dictionary
within it, rows will be an array of dictionaries
each dictionary has an array named elements
each entry in that array is a dictionary
within that, distance is another dictionary
distance contains two strings, with keys "text" and "value"
So if you weren't to do any validation at all, to get to the distance dictionary you might do:
NSDictionary *result = [parser objectWithString:...];
NSLog(#"distance dictionary is: %#"
[[[[[
result objectForKey:#"rows"]
objectAtIndex:0]
objectForKey:#"elements"]
objectAtIndex:0]
objectForKey:#"distance"]
);
Based on your sample code, it looks like you may actually be getting an array of the sorts of dictionary posted rather than the dictionary directly. Obviously adapt if that's the case.
You need to use a JSON parser like SBJSON. This will create a NSDictionary/NSArray with all the values and keys. Then use the normal dictionary and array methods to access the data.

Have TouchJSON return mutable objects?

I am receiving some json from a web service. I parse this using the TouchJSON library.
I keep the data around for the user to change certain values and then I want to return it to the web service.
The JSON object I get contains NSDictionary Objects within the object, like this:
[
{
"id": null,
"created_at": 12332343,
"object": {
"name": "Some name",
"age" : 30
},
"scope": "it stuff",
"kind_id": 1,
"valid": true,
"refering_statement": {
"id": 95
},
"user": {
"id": 1
}
}
]
If I want to change values in this dictionary, I can't because the returned objects from TouchJSON are not mutable.
Is there a way to have have TouchJSON return mutable objects?
or is there a way to have Objective C make an NSDictionary and all its children mutable?
or do I have to just go through every NSDictionary in NSDictionary and copy all data into a mutable copy and then reinsert everything?
Hope someone can help me out on this one:) thanks in advance.
TouchJson has an option to return mutable object rather than normal. (I found it by looking at source code.) Default is to return its "copy", not "mutablecopy".
NSError *error = nil;
jsonString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF32BigEndianStringEncoding];
CJSONDeserializer *jsondeserializer = [CJSONDeserializer deserializer];
jsondeserializer.scanner.options = kJSONScannerOptions_MutableContainers;
NSMutableDictionary *jsonitems = [[NSMutableDictionary alloc] initWithDictionary:[jsondeserializer deserializeAsDictionary:jsonData error:&error]];
You can create a mutable dictionary from a dictionary like this.
(assuming your json parsed dictionary was named jsonDictionary)
NSMutableDictionary *userDictionary = [NSMutableDictionary dictionaryWithDictionary:jsonDictionary];
Hope that solves it for you.