JSON Sort String - iphone

framework.
Hi I'm using json-framework.
How to get sorted string when using JSONRepresentation method?
Here is my code:
NSMutableDictionary *tUserIDParam = [NSMutableDictionary dictionary];
[tUserIDParam setObject:#"UserID" forKey:#"#key"];
[tUserIDParam setObject:#"string" forKey:#"#type"];
[tUserIDParam setObject:#"mark" forKey:#"#text"];
NSMutableDictionary *tPasswordParam = [NSMutableDictionary dictionary];
[tPasswordParam setObject:#"Password" forKey:#"#key"];
[tPasswordParam setObject:#"string" forKey:#"#type"];
[tPasswordParam setObject:#"123456" forKey:#"#text"];
NSArray *tParams = [NSArray arrayWithObjects:tUserIDParam,tPasswordParam, nil];
NSDictionary *tParam = [NSDictionary dictionaryWithObject:tParams forKey:#"param"];
NSMutableDictionary *tRequests = [NSMutableDictionary dictionary];
[tRequests setObject:[NSNull null] forKey:#"key"];
[tRequests setObject:[NSNull null] forKey:#"basic"];
[tRequests setObject:tParam forKey:#"conditions"];
NSDictionary *tRequest = [NSDictionary dictionaryWithObject:tRequests forKey:#"request"];
NSString *tJSONStrFromDict = [tRequest JSONRepresentation];
I want to get JSON string like:
{"request":{"key":null,"basic":null,"conditions":{"param":[{"#key":"UserID","#type":"string","#text":"mark"},{"#key":"Password","#type":"string","#text":"123456"}]}}}
But I got this string from above code:
{"request":{"basic":null,"conditions":
{"param":[{"#text":"mark","#key":"UserID","#type":"string"},{"#text":"123456","#key":"Password","#type":"string"}]},"key":null}}
I try to use SBJSONWriter sortKeys property,it does not work...
Have any way to solve my problem?
Thanks!

NSMutableDictionary instance do not preserve the order of elements, neither in alphabeticallz order nor in the order they were inserted. This is independent of JSON.
Furthermore, JSON's data model for object doesn't guarantee order either. If you want a certain order, you'll have to use JSON arrays for the ordered parts.
BTW.: The effect of SBJSONWriter sortKeys is to output the object elements (or properties) alphabetically sorted by the key name. This is what you get.

Related

How to set array value and key in NSDictionary in iphone?

Here i am using NSMutableArray to store date, then i tried to set key and assign ArrayValue in dictionary but the app crashed, please help me
Thanks in ADvance
Here i tried the code for your reference:
[DateArray addObject:dateString]; //NSMutablArray
NSMutableDictionary *myDictionary =[[NSMutableDictionary alloc]init];
[myDictionary setObject:DateArray forKey:#"Date"]; //put array value and set key in NSDictionary.
NSDictionary Class is immutable. You must convert to NSMutableDictionary.
If you are using XCode version 4.4 or later you can jus do this:
[dateArray addObject:dateString]; //NSMutablArray
NSDictionary *myDictionary = #{ #"Date", dateArray };
You are using NSDictionary. You should use NSMutableDictionary.
NSDictionary is immutable. If you want to use NSDictionary then use below method:
- (id)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys;
You're using an NSDictionary when you should be using NSMutableDictionary
Try this line :
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
Most of the collection classes in iOS have a mutable and nonmutable version (i.e.
NSArray -> NSMutableArray
NSSet -> NSMutableSet
NSDictionary -> NSMutableDictionary
(and others)
A mutable version will let you modify the contents. However, if you know you're not going to change it then a non mutable version will be slightly faster to use.
You can (usually) get a mutable class from a nonmutable one by using the mutableCopy method i.e.
// This array can't be changed
NSArray *myArray = #[ #"A", #"B", #"C" ];
// This array contains everything from the previous array but can now be modified
MSMutableArray myArray2 = [myArray mutableCopy];
NB : There are also other classes that have mutable subclasses i.e. NSURL -> NSMutableURL
Do it like this:
for(int i=0;i<[DateArray count]; i++)
{
[myDictionary addObject:[DateArray objectAtIndex:i] forKey:#"Date"];
}

Retrive values from NSDictionary

I am trying to retrieve the values from my NSDictionary however I am running into errors, I was wondering if someone might be able to help me with my solution.
I have 18 values, not all are shown here that I am checking, when the correct key is reached I would like to take the value in the NSDictionary and pass it into one of my NSString variables.
Below is an example of what I am trying to do however like I say I am having several issues
for (id key in searchData) {
if ([[searchData objectForKey:key] isEqualToString:#"Code"]) {
codeSeries = [searchData objectForKey:key];
}
else if ([[searchData objectForKey:key] isEqualToString:#"ID"]) {
IDSeries = [searchData objectForKey:key];
}
// ...
However, when I try to log out any of the values, they all return Null. I have checked the dictionary before hand and the values are all most definitely in there, so I am thinking there is something wrong with my code above.
Any help would be greatly appreciated.
Update
This is how I create the NSDictionary
//start of mymethod...
NSDictionary *sendSeriesDictionary = [[NSDictionary alloc] init];
// Keys for sendSeriesDictionary
NSArray *keys = [NSArray arrayWithObjects:#"Code", #"ID", nil];
// Objects for keys that are for sendSeriesDictionary
NSArray *objects = [NSArray arrayWithObjects: [NSNull null], IdString, nil];
// Add keys and objects to NSDictionary
sendSeriesDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
[engineRequests SeriesSearch:sendSeriesDictionary]; // this is where I send the NSDictionary over to where I want to read it.
//end of mymethod
You've got several problems. First, you mix up keys and values (like Tom said). Second, you have a possible memory leak where you create the dictionary, or at least a unnecessary instantiation.
Try this for creating the dictionary:
// Keys for sendSeriesDictionary
NSArray *keys = [NSArray arrayWithObjects:#"Code", #"ID", nil];
// Objects for keys that are for sendSeriesDictionary
NSArray *objects = [NSArray arrayWithObjects: [NSNull null], IdString, nil];
// Add keys and objects to NSDictionary
NSDictionary *sendSeriesDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
Retrieving the values can be done like this:
codeSeries = [searchData objectForKey:#"Code"];
IDSeries = [searchData objectForKey:#"ID"];
In your first loop you looped through all the keys, got their values and then compared those to the key again. Which makes no sense.
Are you mixing keys and values ?
Maybe you just want codeSeries = [searchData objectForKey:#"Code"]; ?

Moving through a NSDictionary getting objects that you do not know the 'Key' for? IOS

I have a NSDictionary that I get from a webservice. Each object in this dictionary contains an array. I do not know how many objects there are going to be in the NSDictionary, or what the 'Key' for each object is going to be beforehand. I only know that it will be a Dictionary of arrays.
How can I enumerate through the dictionary reading out the name of the Object and its content into arrays?
All my dealings with Dictionaries so far I could use
[anotherDict objectForKey:#"accounts"]
because I know the 'Keys; to expect beforehand.
Many Thanks,
-Code
NSDictionary has the method: enumerateKeysAndObjectsUsingBlock: since iOS 4.0. It's very straightforward, it receives a block object to operate on entries in the dictionary.
An example:
[anotherDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSArray *arr = obj;
//Do something
}
NSDictionary class has an instance method -allKeys which returns an NSArray with NSStrings for all the keys.
Simplest Way WOuld be to fetch allKeys via the allKeys instance method
NSArray *keys = [myDictionary allKeys];
then iterating over dictionary with for each key.
for (NSString *k in keys)
{
id object = [myDictionary objectForKey:k];
}
You can also get keys in order as if values were sorted using
NSArray *sortedKeys = [myDictionary keysSortedByValueUsingSelector:#selector(compare:)];
you can do this :
NSArray * keys = [dictionnary allKeys];
for (NSString *key in keys) {
NSArray *tmp = [dictionnary objectForKey:key];
}
i am not a pro but i know that you can get all the keys of an dictionary
NSLog(#"%#",[Your_Dictionary allKeys]);
This will give an array of keys in that dictionary.

iOS - deleting all entries containing a key on all NSDictionaries stored inside a main NSDictionary

I have a main NSMutableDictionary that contains a collection of others NSMutableDictionary.
The thing goes like this:
NSMutableDictionary *subDict1 = [NSMutableDictionary dictionaryWithObjectsAndKeys:
obj1, #"name",
obj2, #"color",
nil];
NSMutableDictionary *subDict2 = [NSMutableDictionary dictionaryWithObjectsAndKeys:
obj3, #"name",
obj4, #"color",
obj5, #"address",
obj6, #"phone",
obj7, #"color",
obj8, #"parent",
nil];
NSMutableDictionary *subDict3 = [NSMutableDictionary dictionaryWithObjectsAndKeys:
obj0, #"name",
obj9, #"parent",
objA, #"site",
objB, #"surname",
objC, #"label",
nil];
These sub dictionaries may have different number of entries and the keys may vary. Some may have keys with the same name.
They are stored in a main dictionary like this:
NSMutableDictionary *mainDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
subDict1, #"1",
subDict3, #"3",
subDict2, #"2",
nil];
I want at one shot, remove all entries in all sub dictionaries that have a specific key.
I know I can iterate thru the dictionaries and sub dictionaries, but I also know that Dictionaries have smart ways to do that using predicates and other stuff, but I am not seeing how. I am trying to find that because the method this will run is a little bit tricky and have to do it as fast as possible and I am not sure if normal iteration with loops or whatever will be fast enough...
Any clues? thanks.
Here's a recursive method that doesn't care how many levels deep the target key is. (haven't tried it) ...
- (void)removeKey:(NSString *)keyToRemove fromDictionary:(NSMutableDictionary *)dictionary {
NSArray *keys = [dictionary allKeys];
if ([keys containsObject:keyToRemove]) {
[dictionary removeObjectForKey:keyToRemove];
} else {
for (NSString *key in keys) {
id value = [dictionary valueForKey:key];
if ([value isKindOfClass:[NSMutableDictionary self]]) {
[self removeKey:keyToRemove fromDictionary:(NSMutableDictionary *)value];
}
}
}
}
You'll need to just iterate through all the subdirectories and remove the appropriate key-value pairs manually. You shouldn't worry if it's fast enough at this point. Rather, create a working implementation and test/measure it. If it's too slow, then you can profile it and come up with ways to improve performance. Premature optimization is a bad thing.
NSArray* keys = [NSArray arrayWithObjects:#"name", #"address", nil];
[dics removeObjectsForKeys:keys]; //Or sub dics

Create a dictionary property list programmatically

I want to programatically create a dictionary which feeds data to my UITableView but I'm having a hard time with it. I want to create a dictionary that resembles this property list (image) give or take a couple of items.
I've looked at "Property List Programming Guide: Creating Property Lists Programmatically" and I came up with a small sample of my own:
//keys
NSArray *Childs = [NSArray arrayWithObjects:#"testerbet", nil];
NSArray *Children = [NSArray arrayWithObjects:#"Children", nil];
NSArray *Keys = [NSArray arrayWithObjects:#"Rows", nil];
NSArray *Title = [NSArray arrayWithObjects:#"Title", nil];
//strings
NSString *Titles = #"mmm training";
//dictionary
NSDictionary *item1 = [NSDictionary dictionaryWithObject:Childs, Titles forKey:Children , Title];
NSDictionary *item2 = [NSDictionary dictionaryWithObject:Childs, Titles forKey:Children , Title];
NSDictionary *item3 = [NSDictionary dictionaryWithObject:Childs, Titles forKey:Children , Title];
NSArray *Rows = [NSArray arrayWithObjects: item1, item2, item3, nil];
NSDictionary *Root = [NSDictionary dictionaryWithObject:Rows forKey:Keys];
// NSDictionary *tempDict = [[NSDictionary alloc] //initWithContentsOfFile:DataPath];
NSDictionary *tempDict = [[NSDictionary alloc] initWithDictionary: Root];
I'm trying to use this data of hierachy for my table views.
So I was wondering how can I can create my property list (dictionary) programmatically so that I can fill it with my own arrays.
I'm still new with iPhone development so bear with me. ;)
This is a situation where "teach a man to fish" is a vastly more helpful approach than "give a man a fish". Once you understand the basic principles and the NSDictionary API, it becomes much easier to craft your own custom solution. Here are a few observations and learning points:
The method +dictionaryWithObject:forKey: is used to create an NSDictionary with a single key-value pair. It will not accept comma-separated arguments after each colon (:) in the method call, just one. To create a dictionary with multiple key-value pairs, use one of 2 related methods: +dictionaryWithObjects:forKeys: which accepts two NSArray objects containing values and keys, or +dictionaryWithObjectsAndKeys: which alternates (object, key, object, key) with a terminating nil argument.
Simplify the creation code. You don't need a million local variables just to create the thing. Use inline arguments where it makes sense. One way to do this it to build up your dictionary in code as an NSMutableDictionary, then (if necessary) make an immutable copy of it by calling -copy on it. (Remember that a copy method returns a new object that you must release to avoid memory leaks.) That way you don't have to have a variable for every single value so you can do a "one shot" creation of the structure(s) at each level.
Use +arrayWithObject: for creating an NSArray with a single object.
(Style suggestions) Never use an uppercase letter to begin the name of a variable, method, or function. (Notice that SO highlights leading-caps variables like class names.) It will certainly help others who read your code from being confused about your intent by your naming scheme.
Just to give you a flavor of what creating the dictionary in the linked image might look like in code... (I'm ignoring your chosen variable names and using both different approaches for completeness.)
NSDictionary *item1 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"Screen J",[NSNumber numberWithInt:3],nil]
forKeys:[NSArray arrayWithObjects:#"Title",#"View",nil]];
NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
#"Screen I", #"Title",
[NSArray arrayWithObject:item1], #"Children",
nil];
...
I am not sure I understand the basic objective here.
It seems like at runtime, you are constructing a deep dictionary with many child nodes. But you are constructing this all with static code... why can you not simply make a plist (like the one you had an image of) and read that into an NSDictionary? Both NSDictionary and NSArray have methods that let you simply read in a file and get a whole filled out object. Then it is WAY easier to edit and to understand. That method is dictionaryWithContentsOfFile.
If all of the data is truly created at runtime before it is put into the dictionary, then it seems like you would want a very different, recursive, style of code rather than the flat examples given.
Lastly, I personally dislike the dictionaryWithObjects:forKeys: method in NSDictionary for building a dictionary. If you have to do things that way I greatly prefer the alternate method dictionaryWithObjectsAndKeys: which does the same thing but keeps the keys with the objects:
NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
#"Screen J",
#"Title",
[NSNumber numberWithInt:3],
#"View"];
NSMutableDictionary *topLevel = [NSMutableDictionary dictionary];
NSMutableDictionary *item1 = [NSMutableDictionary dictionary];
NSString *item1title = [NSString stringWithString:#"Title 1"];
NSMutableDictionary *item1children = [NSMutableDictionary dictionary];
// create children
NSString *item1child1 = [NSString stringWithString:#"item 1, child 1"];
NSMutableDictionary *item1child2 = [NSMutableDictionary dictionary];
NSString *item1child2title = [NSString stringWithString:#"Title 1-2"];
NSMutableDictionary *item1child2children = [NSMutableDictionary dictionary];
NSString *item1child2child1 = [NSString stringWithString:#"item 1, child 2, child 1"];
NSString *item1child2child2 = [NSString stringWithString:#"item 1, child 2, child 2"];
[item1child2 setObject:item1child2title forKey:#"Title"];
[item1child2children setObject:item1child2child1 forKey:#"item 1 child2 child 1"];
[item1child2children setObject:item1child2child2 forKey:#"item 1 child2 child 2"];
[item1child2 setObject:item1child2children forKey:#"children"];
// add children to dictionary
[item1children setObject:item1child1 forKey:#"item1 child1"];
[item1children setObject:item1child2 forKey:#"item1 child2"];
// add to item 1 dict
[item1 setObject:item1title forKey:#"Title"];
[item1 setObject:item1children forKey:#"children"];
NSMutableDictionary *item2 = [NSMutableDictionary dictionary];
NSString *item2title = [NSString stringWithString:#"Title"];
NSMutableDictionary *item2children = [NSMutableDictionary dictionary];
NSString *item2child1 = [NSString stringWithString:#"item 2, child 1"];
NSString *item2child2 = [NSString stringWithString:#"item 2, child 2"];
NSString *item2child3 = [NSString stringWithString:#"item 2, child 3"];
// add children to dictionary
[item2children setObject:item2child1 forKey:#"item2 child1"];
[item2children setObject:item2child2 forKey:#"item2 child2"];
[item2children setObject:item2child3 forKey:#"item2 child3"];
// add to item 2 dict
[item2 setObject:item2title forKey:#"Title"];
[item2 setObject:item2children forKey:#"children"];
[topLevel setObject:item1 forKey:#"Item 1"];
[topLevel setObject:item2 forKey:#"Item 2"];
first of .. super! thanks .. I really appreciate the explanation and code snippet.
Since you gave me such a good explanation I hope you don't mind me asking a couple more questions.
First, I did as you suggested and this is what I came up with :
(I used my original property list instead of the example this time so this is where the drilldown table gets his( or needs to get his ) treestructure).
http://img509.imageshack.us/img509/7523/picture2lsg.png
NSDictionary *root = [NSMutableDictionary dictionary];
NSDictionary *item1 = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:#"VirtuaGym Online"] forKey:[NSArray arrayWithObjects:#"Title"]];
NSDictionary *item2 = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:#"Do the training"] forKey:[NSArray arrayWithObjects:#"Title"]];
NSDictionary *item3 = ...
[root setObject:item1 forKey:#"Item 1"];
[root setObject:item2 forKey:#"Item 2"];
Also did some research and tried something else with some other input..
NSMutableArray *Rows = [NSMutableArray arrayWithCapacity: 1];
for (int i = 0; i < 4; ++i) {
NSMutableArray *theChildren = [NSMutableArray arrayWithCapacity: 1];
[theChildren addObject: [NSString stringWithFormat: #"tester %d", i]];
NSString *aTitle = [NSString stringWithFormat: #"Item %d", i];
NSDictionary *anItem = [NSDictionary dictionaryWithObjectsAndKeys: aTitle, #"Title", theChildren, #"Children"];
[Rows addObject: anItem];
}
NSDictionary *Root = [NSDictionary withObject: Rows andKey: #"Rows"];
I decided to just test both of these however it does what I want. It gives me a EXC_BAD_ACCESS error.
I was also wondering since I saw you using number in your code snippet, couldn't you also use NSString since that's what the plist uses.. could be totally of here of course
NSDictionary *item1 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"Screen J",[NSNumber numberWithInt:3],nil]
forKeys:[NSArray arrayWithObjects:#"Title",#"View",nil]];
and third a question is about my possible approach to my app.
I have an xml parser which saves certain information in different arrays.
I want to use this information for my drilldown UITableviews (infoFirstScreen[] infoSecondScreen[] infoThirdScreen[]).
The information provided has to be connected like the tree I showed you above.
This is the reason I wanted to build the dictionary in code so I can take the info from my arrays and insert it here.
My question do you think my approach is correct, wrong or is there a faster way?
again really appreciate the explanation ;)