I've found that when using NSDictionary to create the params for an AFNetworking POST request the behaviour is inconsistent. I have multiple POSTs where the params arrive at the server in the same order I created them in the NSDictionary and now creating a new request they are arriving at the server in a different order.
This is how I send them:
NSDictionary *params = #{#"username": #"testuser", #"count": #"6"};
But this is how it arrives on the server:
{"count":"6","username":"testuser"}
Its important for me that it arrive at the server exactly the same as it leaves my app as I hash together values for integrity and can't verify if it arrives in a different order to how it leaves.
I know NSDictionary is by nature not expected to keep the order, is there anyway using NSDictionary or another way I can guarantee the order?
Thanks in advance
You'd have to use an ordered dictionary class. Unfortunately, there's not one in the Foundation framework, but it's fairly easy to create (or even download) your own. This article describes how to create an ordered dictionary class in Objective-C, and includes source code.
Related
Hi In my application I have a login screen where I have to post credentials to C# server.The order which I used is as such below
username
password
domainname
Code:
NSDictionary*disPost=[[NSDictionary alloc]initWithObjectsAndKeys:#"naresh",#"UserName",#"n123",#"Password",#"naresh-in",#"DomainName",nil];
I can able to post the data to server successfully but the credentials order is changing like below.
Password
UserName
DomainName
Due to this reason I am getting an exceptional error from server. Please help me to resolve this issue as soon as possible.
NSDictionary has key-value pairs, it is not ordered. You need an array to keep the order of the elements. You could use 2 arrays (1 for keys the other for values) or use an array for keys (to know the order) and a dictionary for the key-value pairs.
NSDictionary is not an ordered container. If you really want an ordered dictionary then use OrderedDictionay from,
http://www.cocoawithlove.com/2008/12/ordereddictionary-subclassing-cocoa.html
Your question makes me think that its not NSDictionary that you want to use, because with dictionaries you really shouldn't care about the order.
And I think the glitch in your code is probably with the part that sends to the server, try sending them separately, or use another datatype than NSDictionary.
good luck!
I am using AFNetworking to retrieve JSON data from a web service. Part of the response string I get is:
{"DATA":{"LEASE TYPE":"3 Yrs + 0 renew of 0 Yrs","LANDLORD":"","TENANT":"test comp"...
and so on. The order of the key values in the "DATA" dictionary ("LEASE TYPE","LANDLORD","TENANT"...) is important for presentation purposes. However, when AFNetworking calls NSJSONSerialization's:
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
method, the returned dictionary has the keys in a different order.
I notice that the AFJSONRequestOperation object has the server's response stored as an NSString, with everything in the correct order. However I'm not keen on parsing the JSON by hand if I can avoid it.
Can anyone suggest a way that will let me get at / keep the keys in their original order?
Thanks.
If the order is important use an array not a dictionary, dictionaries are be by their nature unordered. Or add an array of dictionary keys in the order desired.
If you have no control over the response that is sent you will have to parse the JSON yourself at least for the ordering.
When you'r creating an NSDictionary, the order will not be the same. I often recognized that dictionaries get ordered by key-name alphabetically.
But when using dictionaries the order doesn't really matter. And they shouldn't!
As the previous answers mentions dictionaries are by nature without order, but you can find here a nice class of OrderedDictionary:
http://www.cocoawithlove.com/2008/12/ordereddictionary-subclassing-cocoa.html
http://projectswithlove.com/projects/OrderedDictionary.zip
I'm writing an iPhone app that loads Menu data from a database in the cloud. I am using AFNetworking (specifically AFJSONRequestOperation) to download the data in appDelegate.
Everything works fine up until this point, but I also need the app to be able to load the menu when the app is offline. To handle this, I want to save the returned JSON data to disc after it is retrieved by the AFJSONRequestOperation call.
My initial strategy was to save the returned JSON as a string, but I can't find a way to get the string response from an AFJSONRequestOperation. It seems silly to make two calls to the web service (one to return a JSON object and the other to return text) although it would be straightforward. I'd like to know if there is a better or more efficient way to do this. I could skip the AFJSONRequest and go for a plain AFHttpRequest but then I would need to construct the JSON object manually.
Is there a better option than either of the two I've thought up? In my opinion, the right answer would involve a single call that constructs the JSON object and also allows me to have access to the original text response, but I am open to hearing alternatives.
Don't save it as the JSON string level. AFNetworking will return the JSON as either an NSArray or an NSDictionary depending on your JSON structure.
You can just save the array or dictionary as a plist.
see -[NSDictionary writeToURL:atomically:] or -[NSArray writeToURL:atomically:]
I would try NSJSONSerialization to save NSData to disk.
Example:
NSData *dataToSave = [NSJSONSerialization dataWithJSONObject:responseObject options:nil error:nil];
id jsonObject = [NSJSONSerialization JSONObjectWithData:dataToSave options:nil error:nil];
Another option would be to take your responseObject from AFNetworking. Presumably a well-formed NSDictionary and simply place it in NSUserDefaults for semi-persistent storage. You need to make sure you don't have any null values in your dictionary as NSUserDefaults does not play nicely with null values.
I have a large number of nested dictionaries and the leaf (or most nested) dictionaries store integer data and integer keys. All the information remains constant (but may change in a future release). I am currently allocating the dictionaries from constants in code but I feel I should be reading that information from XML or similar. I have read about Core information, plists, databases and archives but I don't want the user to be able to change it, I never want to be able to write it (except maybe during the release procedure) and I never want to display it. I would like to be able to hand edit it before release.
What is the best method to store this constant data?
Basically you need to ship your data in files with the app -
XML or JSON are both suitable for this. When I have had to do something similar I used JSON
It works something like this :
Define your JSON in text file (UTF8) and then use the
NSString initWithContentsOfFile to load file contents into a NSString
You can then use the NSJSONSerialization JSONObjectWithData to give you the top level dictionary for your JSON
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
From this you can extract your NSStrings / NSArrays using NSDictionary objectForKey for your data. Obviously the exact format will depend on your JSON format
I have a basic iOS app that interfaces with a Rails app. The idea here is to load all channel objects from my RESTful /channels.json route set up in Rails.
I want to load all of the Channel objects into an NSDictionary in Xcode so that they can easily be identified using the Channel object's ID generated by ActiveRecord -- something along the lines of [dictionary objectForKey:#"1"]
I've had no trouble loading all the Channel objects into an NSArray, but getting them to load into an NSDictionary is proving tough. I've implemented RestKit's didLoadObjectDictionary delegate method, and have set up my JSON response as follows: https://gist.github.com/2504664
I believe I have my mapping set up incorrectly. The mapping for the Channel objects is set up as follows: https://gist.github.com/2504667
When the didLoadObjectDictionary method is called, the objects NSDictionary contains 0 key/value pairs.
How do I go about loading all Channel objects into an NSDictionary so that I can easily refer to them using objectForKey as explained above?
You can still fetch things out of the nsarray using a predicate:
[someArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"id = %#", someId]];
It returns another NSArray (which should have one object).
Alternatively you could use restkit's coredata mappings then simply fetch the object by ID out of core data.