Sort array with ÅÄÖ - iphone

I'm totally new to iPhone/OSX development and I'm trying to sort an NSMutableArray filled with objects in alphabetical order but I fail. Items starting with Å or Ä ends up with items starting with A and items starting with Ö ends up with items starting with O. I have tried different sorting methods that I have found here on Stackoverflow but none of them seems to work (for me at least)
NSSortDescriptor* stationDescriptor = [[NSSortDescriptor alloc]initWithKey:#"name" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray* descriptors = [NSArray arrayWithObject:stationDescriptor];
[stations sortUsingDescriptors:descriptors];
[stations sortUsingComparator:^NSComparisonResult(Station* obj1, Station* obj2){
return [[obj1 name] localizedCaseInsensitiveCompare:[obj2 name]];
}];
Ok, progress! I have been successful in getting this to work by changing the language on the emulator to Swedish, is there any way I can get the same result when the phone is set to English? I know in C# you can send in a reference to a specific culture when sorting/comparing strings.
/Viktor

Looking at the docs for NSString gives you the answer.
You are using localizedCaseInsensitiveCompare: and the docs for this state
blah blah blah
See Also
– compare:options:range:locale:
So jumping to the docs for compare:options:range:locale: you can figure it out. You'll need something like
return [[obj1 name] compare:[obj2 name]
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [obj1 length])
locale:whateverLocaleYouWant];

Related

Set up a NSMutableArray of objects to match a string value

I'm using the value of two sliders as the first search criteria.
Now I want a second criteria. I have a
NSMutableArray *suitsArray;
which is containing up to 10 words, or it could be empty (0 words). Example of array:
2012-08-12 03:13:14.825 App[4595:f803] The content of array is(
mushroom,
grill,
pizza
)
What I want is this:
If suitsArray is like above, containing words mushroom, grill and pizza
and the "Suits" value in a dictionary is: "This wine suits mushroom dishes, grilled food, pizza and chicken."
This dictionary is added to searchResultsArray, same with all other dictionaries where "Suits" value containing words mushroom, grill and pizza.
But if suitsArray is empty of objects, skip this critera.
But I'm not sure how to write the code for it. Can you help me on it?
-(IBAction)searchButtonPressed:(id)sender{
resultObjectsArray = [NSMutableArray array];
for(NSDictionary *object in allObjectsArray)
{
NSString *objectPrice = [object objectForKey:#"75 cl price"];
NSString *suitsString = // the words in suitsArray
NSString *objectSuits = [object objectForKey:#"Suits"];
BOOL priceConditionGood = YES;
if (minPrisSlider.value <= maxPrisSlider.value && (winePrice.floatValue < minPrisSlider.value || winePrice.floatValue > maxPrisSlider.value))
priceConditionGood = NO;
if (priceConditionGood)
[resultObjectsArray addObject:object];
}
ResultsTableViewController *nextController = [[self storyboard] instantiateViewControllerWithIdentifier:#"ResultsController"];
nextController.objectsArray = [[NSMutableArray alloc]initWithArray:resultObjectsArray];
[self.navigationController pushViewController:nextController animated:YES];
}
It would be better to see if suitsArray contains the string objectSuits, rather than using rangeOfString.
if ([suitsArray containsObject:objectSuits]);
[resultObjectsArray addObject:object];
After edit: I think I understand now. This method looks at each word in suitsArray, and if it finds any of them in objectSuits, then object is added to the resultObjectArray.
for (NSString *aWord in suitsArray) {
if ([objectSuits rangeOfString:aWord].length == aWord.length) {
[resultObjectArray addObject:objectSuits];
break;
}
}
Second Edit: After further thought, the above code has a flaw in the logic that may or may not be important -- because it uses rangeOfString it will find words inside other words. So, if objectSuits was "This wine goes well with cheesecake" and suitsArray contained the word cheese, it would find a match (I can't imagine a wine that would be good with cheese would be good with cheesecake). So, here is a better solution, I think, that breaks objectSuit up into individual words and puts them into a set. suitsArray is also converted to a set, so that we can use intersectsSet: to find if there are any common words.
NSCharacterSet *sepSet = [NSCharacterSet characterSetWithCharactersInString:#" ,.;"];
NSArray *words = [objectSuits componentsSeparatedByCharactersInSet:sepSet];
NSSet *objectSuitsWords = [NSSet setWithArray:words];
NSSet *suitsSet = [NSSet setWithArray:suitsArray];
BOOL ans = [suitsSet intersectsSet:objectSuitsWords];
So, if ans is 1, then that object should be added to the results array. Notice that sepSet starts with a space and includes a comma, period, and semicolon. There might be other things you might want to include, but I think this should work in most cases.

SBJson parsing help iphone

im currently trying to parse some json data on the iphone.
I have been trawling the web for examples, but none seem to suit my purpose, i am using SBJson.
What I want is to be able to get an NSArray of Titles, Artisits, Status, etc. so that I can display them on a table view. Any help would be great, so far all i get is an array of "Values".
JSON = {"values":
[
{"Status":"N", "Filename":"RD207T04", "Title":"Simple Man (Explicit)", "Artist":"DIAFRIX F/DANIEL MERRIWE", "Release":"May11"},
{"Status":"N", "Filename":"CR221T27", "Title":"Midnight City", "Artist":"M83", "Release":"Dec11"},
{"Status":"N", "Filename":"ED211T03", "Title":"I\"ll Be Your Man", "Artist":"JAMES BLUNT", "Release":"Jul11"}
]}
You don't want an array of titles, artists, etc. You want the array of NSDictionarys represented by the values key. Then you can do:
cell.textLabel.text = [[valuesArray objectAtIndex:indexPath.row]valueForKey:#"Title"]];
inside your cellForRowAtIndexPath: delegate method. If you do not have this already, this is how to get that array:
NSArray *valuesArray = [[myJsonString JSONValue]objectForKey:#"values"];
Thanks mate, I was definately over complicating things:
The end code was this:
NSArray *valuesArray = [[playlist JSONValue] objectForKey:#"values"];
NSString *test = [[valuesArray objectAtIndex:0]valueForKey:#"Title"];
NSLog(#"test = %#", test);
Now all I have to do is iterate through the set :)

parsing JSON object and sub-elements on iphone app

I am building an app that uses a UPC data base API. I am getting back a JSON object, example from here: http://www.simpleupc.com/api/methods/FetchNutritionFactsByUPC.php
{
"success":true,
"usedExternal":false,
"result"
{
"calories_per_serving":"150",
"cholesterol_per_serving":"15",
"cholesterol_uom":"Mg",
"dvp_calcium":"30",
"dvp_cholesterol":"4",
"dvp_iron":"2",
"dvp_protein":"17",
"dvp_saturated_fat":"8",
"dvp_sodium":"10",
"dvp_total_fat":"4",
"dvp_vitamin_a":"10","
"dvp_vitamin_c":"0",
"dvp_vitamin_d":"25",
"fat_calories_per_serving":"25",
"fiber_per_serving":"<1",
"fiber_uom":"G",
"ingredients":"Fat Free Milk, Milk, Sugar, Cocoa (Processed With Alkali),
Salt, Carrageenan, Vanillin (Artificial Flavor),
Lactase Enzyme, Vitamin A Palmitate And Vitamin D3.",
"protein_per_serving":"8",
"protein_uom":"G",
"size":"240",
"units":"mL",
"servings_per_container":"8",
"sodium_per_serving":"230",
"sodium_uom":"Mg",
"total_fat_per_serving":"2.5",
"total_fat_uom":"G",
"trans_fat_per_serving":"0",
"trans_fat_uom":"G",
"upc":"041383096013"
}
}
My problem is with parsing the "ingredients" element, which is a sub list of the object dictionary.
How would you suggest parsing the ingredients list? If I could get it to an NSArray, assuming commas are separators, that would have been great.
I tried to do this, but looks like its just a string, so no way to parse it.
Any suggestion would be more than welcome. Thanks!
//Thats the whole JSON object
NSDictionary *json_dict = [theResponseString JSONValue];
//Getting "results" which has all the product info
NSArray *myArray = [[NSArray alloc] init];
myArray = [json_dict valueForKey:#"result"];
Now how do I get "ingredients" from myArray in an array form?
You're getting result as an array, but (in JSON terminology) it's not an array. It's an object, so use an NSDictionary. Something like this:1
NSDictionary *result = [json_dict objectForKey:#"result"];
Then you can get the inner ingredients object from that:
NSString *ingredients = [result objectForKey:#"ingredients"];
Edited as per #Bavarious' comment.
1Apologies for glaring errors, as I'm not terribly well-versed in Objective-C. You might need to allocate memory for the returned NSDictionary and NSString pointers; I'm not sure.
Here's all you need to do:
NSDictionary *json_dict = [theResponseString JSONValue];
// Use a key path to access the nested element.
NSArray *myArray = [json_dict valueForKeyPath:#"result.ingredients"];
EDIT
Whoops, Matt's right. Here's how to deal with the string value:
// Use a key path to access the nested element.
NSString *s = [json_dict valueForKeyPath:#"result.ingredients"];
NSArray *ingredients = [s componentsSeparatedByString:#", "];
Note that you might need to trim the '.' character off the last element of the array.

Get objects from a NSDictionary

I get from an URL this result :
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
it looks like this :
[{"modele":"Audi TT Coup\u00e9 2.0 TFSI","modele_annee":null,"annee":"2007","cilindre":"4 cyl","boite":"BVM","transmision":"Traction","carburant":"ES"},
{"modele":"Audi TT Coup\u00e9 2.0 TFSI","modele_annee":null,"annee":"2007","cilindre":"4 cyl","boite":"BVM","transmision":"Traction","carburant":"ES"}]
So it contains 2 dictionaries. I need to take the objects from all the keys from this result. How can I do this?
I tried this : NSDictionary vehiculesPossedeDictionary=(NSDictionary *)result;
and then this : [vehiculesPossedeDictinary objectForKey:#"modele"]; but this is not working.
Please help me... Thanks in advance
What you have is a JSON string which describes an "array" containing two "objects". This needs to be converted to Objective-C objects using a JSON parser, and when converted will be an NSArray containing two NSDictionarys.
You aren't going to be able to get your dictionary directly from a string of JSON. You are going to have to going to have to run it through a JSON parser first.
At this point, there is not one build into the iOS SDK, so you will have to download a third-party tool and include it in your project.
There are a number of different JSON parser, include TouchJSON, YAJL, etc. that you can find and compare. Personally, I am using JSONKit.
#MatthewGillingham suggests JSONKit. I imagine it does fine, but I've always used its competitor json-framework. No real reason, I just found it first and learned it first. I do think its interface is somewhat simpler, but plenty of people do fine with JSONKit too.
Using json-framework:
require JSON.h
...and then
NSString *myJsonString = #"[{'whatever': 'this contains'}, {'whatever', 'more content'}]";
NSArray *data = [myJsonString JSONValue];
foreach (NSDictionary *item in data) {
NSString *val = [item objectForKey:#"whatever"];
//val will contain "this contains" on the first time through
//this loop, then "more content" the second time.
}
If you have array of dictionary just assign objects in array to dictionary like
NSDictionary *dictionary = [array objectAtIndes:0];
and then use this dictionary to get values.

Looping through an dictionary; why do I not get the keys alphabetically?

I am writing an iPhone app using S7Graphview and I have saved some dates and results to a .plist as keys and values in a dictionary, both as strings. My plist looks like this:
<dict>
<key>2011-05-11</key>
<string>23</string>
<key>2011-05-12</key>
<string>23</string>
<key>2011-05-13</key>
<string>23</string>
<key>2011-05-14</key>
<string>43</string>
<key>2011-06-14</key>
<string>43</string>
</dict>
Then I use this loop to load those values into the graphview:
NSMutableDictionary* dictionary = [[NSMutableDictionary alloc]init];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
int i = 1;
if ([dictionary count] > 0) {
for (NSString* key in dictionary){
NSString* verdiString = [dictionary objectForKey:key];
CGFloat verdi = [verdiString intValue];
NSDate *dato = [[NSDate alloc]init];
NSLog(#"key=%# value=%#", key, [dictionary objectForKey:key]);
dato = [self stringTilDato:key];
[items.list_ addObject:[[GraphInfo alloc] initWithID:i name:verdiString value:verdi date:dato]];
i++;
}
}
The "stringTilDato" method converts the date string to a NSDate. The values get loaded into the items.list, but in the wrong order! The NSLog reports:
key=2011-05-14 value=43
key=2011-05-13 value=23
key=2011-05-12 value=23
key=2011-06-14 value=43
key=2011-05-11 value=23
key=2011-05-14 value=43
key=2011-05-13 value=23
key=2011-05-12 value=23
key=2011-06-14 value=43
key=2011-05-11 value=23
(Don't know why it goes through the keys twice, btw, but I dont't believe that's important). I thought the keys would be read alphabetically, or at least in the order of the plist. Why does the plist get loaded into the dictionary in this order, or is it my loading loop that is the problem?
Hope there is someone out there who can help me :)
A dictionary is not an ordered data structure. You can assume no particular order of the keys, and adding or removing a key can change the order completely. If you need an ordered data structure then use an array, or after getting all the keys sort them.
The documentation for NSDictionary says specifically:
The order of the elements in the array
is not defined.
However, if you want the keys sorted in a particular order, there are at least three methods that return a sorted array of keys. Look at the NSDictionary reference page for methods starting with "keysSortedBy..."
Dictionaries do not ensure an ordered key output. If you want the keys displayed in a particular order, you will have to sort them prior to accessing their values and printing the result.