NSDictionary objectForKey is returning nil value - objective-c

I have a dictionary like this
123456
{
"aaa"
"aaav"
}
But when i try to get these values in NSArray using objectForKey, I am getting nil.
The key I am using is a string.
Code :
NSArray *arr = [userdetails objectForKey:str]
Where userdetails is an NSDictionary and str is NSString which contains the key.

NSDictionary cannot contain nil objects. There are two possibilities to get a nil back from objectForKey:
Your dictionary itself has not been initialized, or
There is no object for the key that you have specified.
Please make sure that you have created an instance of your NSDictionary or a compatible class (say, NSMutableDictionary) and assign it to the variable prior to querying it for the key. Then make sure the key in question contains an object.

Related

How to create a NSMutableDictionary that won't crash when assigned nil?

Is there a way to create a NSMutableDictionary category that won't crash when assigned a nil value? There is an objectForKeyedSubscript method that we can override for getting the value, but I am not finding the setter version.
I want my dictionary to not crash even when it's assigned nil through subscript.
e.g.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[#"test"] = nil; //won't crash here
I don't know what your use case is but if you are just trying to assign an empty value to a key have you looked at NSNull? If you assign a key in a dictionary to [NSNull null] it will give you most of the benefits of a nil value.
You can use 'setValue:forKey:' to set any value (including nil) in the dictionary
- (void)setValue:(id)value forKey:(NSString *)key
Adds a given key-value pair to the dictionary.
Note that when using key-value coding, the key
must be a string (see “Key-Value Coding Fundamentals”). Discussion
This method adds value and key to the dictionary using
setObject:forKey:, unless value is nil in which case the method
instead attempts to remove key using removeObjectForKey:.
You can’t do this in Objective-C. However, the code you posted does not crash.

NSDictionary assign variable from key in loop

I've got an NSDictionary loop like this:
NSMutableDictionary *readDict = [[NSMutableDictionary alloc] initWithContentsOfFile:plist];
NSDictionary *keys = [readDict objectForKey:data]; //Dictionary
for(NSString *object in keys) {
NSData *(current object name) = [keys objectForKey:object]; //Dictionary
}
// Can I assign ^ the object name to a new NSData var as it loops?
Is it possible to assign a variable name from the object name as it loops?
Objective-C is basically C with a few extensions. In your vast knowledge of the C language, have you ever seen a way to create variables at runtime? I haven't. So if I figured out correctly what you want to do, you can't.
And what is "data"? Is it a variable containing a string? The line
NSDictionary *keys = [readDict objectForKey:data]; //Dictionary
assumes that the dictionary readDict has one key-value pair where the key is equal to the string contained in the variable data, and the value is an NSDictionary. Is that what you wanted?
Next, a for loop running over a dictionary will run over the keys in that dictionary. So in
for(NSString *object in keys)
the name "object" is badly chosen, because it is actually a key.
Usually NSDictionary will either contain keys with know values, and you'd never think of using a for-loop to access them. Or you have a dictionary that can contain any number of unknown keys and you want to process them one after the other. You wouldn't have different variables.

take nsdictionary and nsstring values from a nsdictionary

I have a function that returns an NSDictionary named data. It contains 2 objects: a NSDictionary object with the key currency_data and an NSString object with the key time.
I want to pass :
the string value with the key time to a new NSString object
the NSDictionary object with the key currency_data to a NSMutableDictionary variable.
How can I do that?
Depending on whether you use ARC. With ARC your example should work, without ARC you need to retain at least the string values.
NSDictionary *dataDict = [foo data];
NSMutableDictionary *currency_dict= [[NSMutableDictionary alloc] initWithDictionary:dataDict[#"currency_data"]];
NSString *time = [data[#"time"] retain];
What anoop-vaidy meant is I think, if you need a mutable dictionary, create that in the data call directly and pass it out. Another note: You can use your knowledge of you data structure in a better way. Instead of building a dictionary with 2 keys, use the first value ( the time string) as the key and the second (the currency dict) as the value. You can access values and keys in dictionaries quite easily
NSArray *value = dict.allValues;
NSArray *keys = dict.allKeys;

Save part of NSDictionary

I have a NSDictionary with a NSString and NSArray
I have to save only the NSArray in a variable without knowing the key.
Is this possible?
If I'm understanding you correctly, you have a dictionary that contains both an NSString and an NSArray, and you want to extract just the NSArray, without knowing what the key is.
One way to do that is to look through the dictionary with fast enumeration:
NSString *key;
for(key in someDictionary){
id someObject = [someDictionary objectForKey: key];
}
and then look at the objects to see which one is an NSArray:
if ([someObject isKindOfClass:[NSArray class]]) {
// do something with the array
}
(obligatory warning: explicitly checking an object's class is often a sign of a flawed design. In most cases, you should be checking for behavior (-respondsToSelector), not class identity)

Unique keys in NSDictionary - how to check given keys are copies?

I have an NSDictionary in which I use my own classes (NSObject subclasses) as keys and would like to make sure that I do not include the same key twice. However, because NSDictionary copies its keys, if I try to check whether an object is in the dictionary, it never thinks it is.
For example,
MyClass* obj = [[MyClass alloc] init];
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject:someObj forKey:obj];
if ([[dict allKeys] contains:obj]) // always returns false
// obj is already in dict
else
// add obj to dict etc.
Similarly, if I want to change the object associated with this key, it seems to create a new entry.
// dict is empty
// say [obj description] gives 'MyClass : 0x1' - (impossible address?)
[dict setObject:someObj forKey:obj];
// dict: { 'MyClass : 0x2' = someObjDesc }
[dict setObject:someOtherObj forKey:obj];
// dict: { 'MyClass : 0x2' = someObjDesc , 'MyClass : 0x3' = someOtherObjDesc }
Also, this same thing leads to not being able to access the items in the dictionary from the original object
[dict setObject:someObj forKey:obj];
[dict objectForKey:obj]; // returns null
So, as far as the uniqueness is concerned, would I be best off keeping track of the keys in a separate array or is there a better way of doing this.
I considered implementing an isEqual method based on a unique variable (such as a name) but didn't think that was the Right Thing to do.
Background (in case it turns out that maybe I'm just using the wrong thing entirely):
I want to keep track of information about a group of people going to different places. So each person at each place has some info. What I've done is used nested dictionaries so the key to the main dictionary is a Person object and the object another dictionary. This latter dictionary has key Place and info as the object. I think this is Java syntax but something like > (the array holds the info). I want to be able to add a Person only if the don't already exist, add a Place (for each person), change the array.
Any help on any of this would be greatly appreciated!
You should always use NSStrings as keys for dictionaries, especially if you are new at objective-C. There are a few things that I can see you are doing wrong with your current implementation - you would need to read up on key requirements for NSDictionaries.
You can do what you want with strings as keys - person's name, etc.
The objects in a dictionary have all the info about a certain person:
NSDictionary* personsInfo = [mainDict objectForKey:#"Jane Smith"];
NSString* addressLine1 = [personsInfo objectForKey#"addressLine1"];
--Tom
The simple answer would be to make it so that the MyClass doesn't actually copy anything.
That would be something like changing:
- (id) copyWithZone:(NSZone *)zone {
MyClass * foo = (MyClass *)[super copyWithZone:zone];
[foo configureCopy];
return foo;
}
To:
- (id) copyWithZone:(NSZone *)zone {
return [self retain];
}