I am trying to retrieve the value for a key in a NSDictionary. The dictionary has been initialised with key value pairs both of type string. The trouble is, I cannot seem to retrieve the value with I call objectForKey or valueForKey.
I am able to iterate over the dictionary and print both keys and values.
Can someone point out where im going wrong? Here is my code...
//Set up dictionary with options
keys = [NSArray arrayWithObjects:#"red", #"blue", nil];
values = [NSArray arrayWithObjects:#"1.7", #"2.8", nil];
conversionOptions = [NSDictionary dictionaryWithObject:values
forKey:keys];
Then this is called on the select row in a picker
NSLog(#"... %#", [keys objectAtIndex:row]); //prints out the key
NSString *theString = [keys objectAtIndex:row]; //save it as a string
NSLog(#"The string is... %#", theString); //print it out to make sure im not going crazy
NSLog(#"the value is : %#",[conversionOptions objectForKey:theString]); // I just get NULL here
//NSLog(#"the value is : %#",[conversionOptions valueForKey:theString]); // This doesn't work either, I just get NULL
You're creating a dictionary with an array as the only key and an array for its value! You want the dictionaryWithObjects:forKeys: (plural) factory, not dictionaryWithObject:forKey: (singular) so that each element of the keys array will be used as a distinct key for the respective element of the values array.
I find the dictionaryWithObjectsAndKeys: factory to be more useful most of the time, e.g.:
conversionOptions = [NSDictionary dictionaryWithObjectsAndKeys:#"1.7", #"red", #"2.8", #"blue", nil];
This is how you retrieve a string from a dictionary object
NSString * string = [dictionary objectForKey:#"stringKey"];
Use objectForKey: not valueForKey:.
Make sure conversionOptions is non-nil when you call objectForKey: (which is the right method).
And, yeah, derp -- I missed that the wrong factory method was used. You could do dictionaryWithObjects:andKeys: or do what pmjordan said said.
You absolutely must use objectForKey:, though. valueForKey: is specific to KVC.
Related
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.
Ok so I want to create a temporary NSDictionary from a NSDictionary of nested dictionaries, but I want to deep copy individual items(dictionaries) from the top level dictionary.
The end result is to have a filtered dictionary that i can process and discard without effecting the main dictionary.
That sounds really confusing, so how about a little code to show you what I mean, heres the function i'm working on, this is a rough coding layout, but basically complete in its path of process.
I've looked at reference books and various samples online with no joy.
Cheers,
Darren
- (void)setPricingData
{
// get selected lens option
NSDictionary *aOption = [self.lensOptionsDict objectAtIndex:self._lensOptionsIndex];
if ( aOption == nil )
return;
// get selected lens type
NSDictionary *aType = [self.lensTypesDict objectAtIndex:self._lensTypesIndex];
if ( aType == nil )
return;
// get lens option id and variation_id
NSString *option_id = [aOption valueForKey:#"id"];
NSString *option_variation_id = [aOption valueForKey:#"variation_id"];
// create temp dictionary for type pricing selection
int count = [self.lensTypesDict count];
NSMutableDictionary *aPrices = [[NSMutableDictionary alloc] initWithCapacity:count];
// cycle prices for option id and variation_id matches
for ( NSDictionary *item in self.pricesDict )
{
NSString *variation_id = [item valueForKey:#"variation_id"];
NSString *value_id = [item valueForKey:#"value_id"];
// add matches to temp dictionary
if ( [option_variation_id isEqualToString: variation_id] )
{
if ( [option_id isEqualToString: value_id] )
[aPrices addObject: item];
}
}
// get price from temp dictionary for selected lens type index
NSDictionary *price = [aPrices objectAtIndex:self._lensTypesIndex];
if ( price != nil )
{
// assign values to outlet
self.priceAndStockId = [price valueForKey:#"price"];
self.priceSelected = [price valueForKey:#"price"];
}
// release temp dictionary
[aPrices release];
}
It looks like you're mixing up dictionaries with arrays.
Arrays respond to objectAtIndex whereas dictionaries respond to objectForKeys. Remember that an array is a set of cells that you can index into, starting from 0 all the way up to [array count] - 1.
A dictionary is similar to an array, except that a hash function is used as the indexing method. This means that you need a key to get, or set, and object.
Setting an object in an NSMutableDictionary
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
[myDictionary setObject:anObject forKey:aKey];
Or, you can have an array of keys and corresponding array of objects, and do:
NSDictionary *completeDictionary;
completeDictionary = [NSDictionary dictionaryWithObjects:objectArray
forkeys:keyArray count:[keyArray count]];
In either case, you must have keys for objects. This is in contrast to a regular array in which you can simply do
[myArray addObject:myObject];
To get objects from a dictionary, do
myObject = [myDictionary objectForKey:key];
To get objects from an array, do
myObject = [myArray objectAtIndex:anIntegerIndex];
Finally, your original question pertained to deep copying. To have your dictionary keep an object that won't change, ie, a deep copy, you can do the following:
Assuming I want to store a dictionary within a dictionary, and I have an associated key for the top-level dictionary, I can do the following:
I have an NSMutableDictionary, called topLevelDictionary
I have an NSDictionary, called dictionaryTwo
I have an NSString, which is my key, called myKey.
To make a deep copy of dictionaryTwo, I can do
// assuming topLevelDictionary is previously defined
[topLevelDictionary setObject:[[dictionaryTwo copy] autorelease] forKey:myKey];
In this manner topLevelDictionary will contain a copy of dictionaryTwo whereby if dictionaryTwo changes, the object in topLevelDictionary will not.
I have a dictionary "playerDict" that reads data from a plist where there is names (myKey) with nine associated objects to each key.
I am trying to read all objects for a specific key (myKeys) into an NSMutableArray (theObjects). I have read the class reference and search internet but cannot figure our this, probably very simple, problem.
Among all other test i have done I have tried the following but that returns the key into theObjects and not the objects.
theObjects = [playerDict objectForKey:myKeys];
Anyone that could give a hint?
Here is the code that created the dict, i stripped it:
NSArray *objs = [NSArray arrayWithObjects:[NSNumber numberWithBool:playerObject.diffHard],[NSNumber numberWithBool:playerObject.diffMedium],
[NSNumber numberWithBool:playerObject.diffEasy],[NSNumber numberWithBool:playerObject.currentGame],
[NSNumber numberWithInt:playerObject.currentGameQuestion],[NSNumber numberWithInt:playerObject.currentGameRightAnswer],
[NSNumber numberWithInt:playerObject.currentGameType],[NSNumber numberWithInt:playerObject.nrOfType0Games],
[NSNumber numberWithInt:playerObject.type0Result], nil];
NSDictionary *newPlayerDict = [NSDictionary dictionaryWithObjectsAndKeys:objs, keyString, nil];
Try valueForKey:
You can only store one item per key in an NSDictionary. If you need story multiple items for the same key, you need to first add each of the items to an NSArray (or NSSet) that you instead then set as an object in your dictionary.
If might be useful if you posted the code that creates the dictionary.
Update: It looks like you are already doing this. So:
NSArray *myObjs=[playerDict objectForKey:keyString];
will get you your array. And this:
BOOL diffHard=[[myObjs objectAtIndex:0] boolValue];
BOOL diffMedium=[[myObjs objectAtIndex:1] boolValue];
Will get you the value you stored in the first and second objects of the array. Repeat it for the rest.
I am not quite sure I understand how to do the following.
If I wanted to add e.g. an author and a title (key, value) to a dictionary. Fill that dictionary with data, then have another dictionary for say e.g. k = genre v = artist name and fill it with data.
Then I want to add the dictionaries to an array.
Firstly how is that done? and secondly, what if I allow the user to log their own entries. So I have to textfields on screen, when the user is done, it stores the fields as key value pair in a new dictionary e.g. user's dictionary.
What will I do later when trying to fill a tableview with the users entered data, I dont know the keys or values in that dictionary so how could I retrieve that data?
I mean let's say I want to load the user's dictionary from array index 2 and fill a tableview's cells with each dictionary entry, how is this done? Maybe a method like on an array(get entry.title at index blah blah ), get Key value in dictionary?
How else can one actually get loaded user entered data that they arent aware of the values?
Regards
Add author and title to a dictionary (assuming they're objects that already exist - likely NSString instances in your case):
NSMutableDictionary *books = [[NSMutableDictionary alloc] initWithCapacity:10];
[books setObject:title forKey:author];
Same thing for genre/artist:
NSMutableDictionary *music = [[NSMutableDictionary alloc] initWithCapacity:10];
[books setObject:artist forKey:genre];
Then put them in an array:
NSArray *theArray = [NSArray arrayWithObjects:books, music, nil];
Then to read out the stuff at array index 2:
id key;
NSDictionary *theDictionary = [theArray objectAtIndex:2];
id value;
for (key in [theDictionary allKeys])
{
value = [theDictionary objectForKey:key];
// do something with the value
}
You can get an NSArray of keys in the dictionary using allKeys. Then you can retrieve the values using objectForKey:
for (id key in [myDict allKeys]) {
NSLog(#"key: %#, value: %#", key, [dictionary objectForKey:key]);
}
I have an array of NSDictionaries. How can I pull out the first element in the dictionary?
NSArray *messages = [[results objectForKey:#"messages"] valueForKey:#"message"];
for (NSDictionary *message in messages)
{
STObject *mySTObject = [[STObject alloc] init];
mySTObject.stID = [message valueForKey:#"id"];
stID = mySTObject.stID;
}
There is no "first" element in an NSDictionary; its members have no guaranteed order. If you just want one object from a dictionary, but don't care which key it's associated with, you can do:
id val = nil;
NSArray *values = [yourDict allValues];
if ([values count] != 0)
val = [values objectAtIndex:0];
NSDictionaries are unordered, meaning that there are not first or last element. In fact, the order of the keys are never guaranteed to be the same, even in the lifetime of a specific dictionary.
If you want any object, you can get one of the keys:
id key = [[message allKeys] objectAtIndex:0]; // Assumes 'message' is not empty
id object = [message objectForKey:key];
NSArray has a selector named firstObject that simplifies the code and makes it more readable:
id val = [[yourDict allValues] firstObject];
If yourDict is empty val will be nil, so is not necessary to check the dictionary/array size.
Simplest:
[[dict objectEnumerator] nextObject];
According to Apple, calls to allKeys or allValues incur the cost of creating new arrays:
A new array containing the dictionary’s values, or an empty array if
the dictionary has no entries (read-only)
So, an alternative option that does not incur such cost could look like this:
NSString* key = nil;
for(key in yourDict)
{ // this loop will not execute if the dictionary is empty
break; // exit loop as soon as we enter it (key will be set to some key)
}
id object = yourDict[key]; // get object associated with key. nil if key doesn't exist.
Note: If the dictionary is empty, the key will remain nil, and the object returned will also be nil, we therefore don't need special handling of the case where the dictionary is actually empty.
If someone is still looking for answer for this type of situation then can refer this:
// dict is NSDictionary
// [dict allKeys] will give all the keys in dict present
// [[dict allKeys]objectAtIndex:0] will give from all the keys object at index 0 because [dict allKeys] returns an array.
[[dict allKeys]objectAtIndex:0];
If you have NSDictionary named message,
It's pretty simple:
message[[[message allKeys] objectAtIndex:0]];
But you have to be sure (or better check) that your dictionary has at least one element.
Here is how you can check it:
if ([message allKeys] > 0) NSLog(#"%#", message[[[message allKeys] objectAtIndex:0]]);
But NSDictionary has no guaranteed order, so you probably should use this code only if your dictionary has only one element.
[UPDATE]
It's also good idea to use this if you need to get ANY element of dictionary
Try this:
NSDictionary *firstValue = [responseObject objectAtIndex:0];