I have a NSDictionary with the following layout:
{
1:{
... some data ...
}
...
}
I have a NSNumber object with a integer value of 1, but when I do
[my_dict objectForKey:my_number] it returns null.
If I try and convert NSNumber to a integer via [my dict objectForKey:[my_number intValue]] I get a warning and the program crashes when it reaches that part of the code.
Any help would be greatly appreciated.
Keys in a NSDictionary or NSMutableDictionary must be objects, like NSNumber. They cannot be primitive data types, like int.
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html
Looks like you're trying to use an integer as the key in your NSDictionary. This would be correct with an NSArray, with an NSDictionary actually needs a proper object as a key.
You might have more success in this particular case feeding that data into an NSArray, and accessing it with:
id *someData = [my_array objectAtIndex:1];
Related
This is my first attempt at using NSUserDefaults. I've read every question & answer posted in stackoverflow regarding this subject, but still can't get it to work. I must be missing something basic. The array (allContacts) merely contains a few names and phone numbers. Unless I'm misunderstanding what's happening, both fields are NSStrings. Or are they just pointers to strings? If that's the case, how would I convert them to actual NSStrings? Here's my code to save the array:
- (BOOL)saveChanges
{
NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithArray:allContacts];
[[NSUserDefaults standardUserDefaults] setObject:mutableArray forKey:#"allContacts"];
[[NSUserDefaults standardUserDefaults] synchronize];
return 1;
}
Here my log:
2013-08-07 15:48:17.568 ImOK[5515:907] *** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '(
"Brad Pitt, 1-917-297-1234",
"Marilyn Monroe, 9179291234"
)' of class '__NSArrayM'. Note that dictionaries and arrays in property lists must also contain only property values.
Thanks in advance for any help.
This code "for(id contact in allContacts) { NSLog(#"%#", [contact class]); }" gives me:
2013-08-07 17:11:30.845 ImOK[5569:907] Contacts
2013-08-07 17:11:30.854 ImOK[5569:907] Contacts
so I guess they are not valid property values.
Incidentally, there was no intelligent reason for me to attempt to save the array as an NSMutableArray. I was just experimenting.
From the Apple documentation: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html#//apple_ref/doc/c_ref/NSUserDefaults
A default object must be a property list, that is, an instance of (or
for collections a combination of instances of): NSData, NSString,
NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any
other type of object, you should typically archive it to create an
instance of NSData.
If allContacts is an NSArray, just use that in your setObject:forKey: call. If it's an NSMutableArray, use:
[allContacts copy]
to get a non-mutable copy of the array.
How does one save an enum value to a dictionary?
When I try the following
enum someEnum
{
field0 = 0,
field1 = 1,
field2 = 2,
};
enum someEnum someEnumObject;
and I try to save it to a dictionary using
[NSDictionary dictionaryWithObjectsAndKeys:]
someEnumObject, #"enum",
I get this
warning: Semantic Issue: Incompatible integer to pointer conversion sending 'enum behaviour' to parameter of type 'id'
Use the following to save it to dictionary,
[NSNumber numberWithInt:enumValue], #"enum",
And you can retrieve it as,
enumValue = [[dictionary valueForKey:#"enum"] intValue];
Better use NSNumber literals to convert an enum to an object so that it can be stored in NSDictionary:
[NSDictionary dictionaryWithObjectsAndKeys:#(someEnumObject), #"enum", nil];
Literals provide shorthands to write stuff, this dictionary can be written like:
#{#"enum":#(someEnumObject)};
Read more about literals here:
http://clang.llvm.org/docs/ObjectiveCLiterals.html
An enum is essentially an integer and an NSDictionary stores objects, so you need to convert your enum to an object. An NSNumber would work well for this:
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:someEnumObject], #"enum", nil];
In modern times #(enumValue) is the easier approach.
I have seen some similar problems, but the fix suggested in most does not work for me.
When my game launches, it calls a method, that reads my Plist to find the key "gameProgress" and if it is the first time the game is run, it creates the Plist and add the key "gameProgress" with the value of 0.
It looks like this:
else {
// create it
NSLog(#"dictionary didn't exist, creating...");
dict = [NSMutableDictionary dictionaryWithCapacity:30];
// create a NSNumber object containing the
// integer value 0 and add it as 'gameProgress' to the dictionary.
NSNumber *numberOfCompletedLevels = [NSNumber numberWithInt:0];
[dict setObject:numberOfCompletedLevels forKey:#"gameProgress"];
// write dictionary to Documents directory...
NSLog(#"writing to %#...", plistPath);
[dict writeToFile:plistPath atomically:YES];
}
[self setLevelsCompleted:[[dict objectForKey:#"gameProgress"]intValue]];
NSLog(#"levels completed is now: %i "), levelsCompleted;
// show the contents of the dictionary in the console
NSLog(#"dictionary values...:");
for (id key in dict) {
NSLog(#"key=%#, value=%#", key, [dict objectForKey:key]);
}
funny thing is, when the code is run, the first NSLog tells me that it sets the "levelsCompleted" variable to 1026944, but when I print the contents of the dictionary, it tells me that the value of "gameProgress" is 0.
clearly something is wrong, and with the intValue not working, i tried with (int) casting, but again unsuccesful.
Does anyone have an idea?
Thank you in advance
regards
Peter
You wrote: NSLog(#"levels completed is now: %i "), levelsCompleted
The , levelsCompleted should go inside the parentheses. As it is, you're not passing an argument to go with the %i and it's grabbing random garbage that happens to lie where the argument would have been.
Incidentally, the reason this code is valid (though incorrect) is because, outside of an argument list, a comma is an operator. It executes the thing on its left-hand side, discards its value and returns the value of the thing on its right.
Well i have tried your code, and it seems to have no issue,
// create a NSNumber object containing the // integer value 0 and add it as 'gameProgress' to the dictionary.
NSNumber *numberOfCompletedLevels = [NSNumber numberWithInt:0];
[dict setObject:numberOfCompletedLevels forKey:#"gameProgress"];
int levelsCompleted = [[dict objectForKey:#"gameProgress"]intValue];
NSLog(#"levels completed is now: %i ", levelsCompleted);
// show the contents of the dictionary in the console
NSLog(#"dictionary values...:");
for (id key in dict)
{
NSLog(#"key=%#, value=%#", key, [dict objectForKey:key]);
}
And the Console output is
2011-01-26 22:30:54.532 Practice[8809:207] dictionary didn't exist, creating...
Current language: auto; currently objective-c
2011-01-26 22:30:56.187 Practice[8809:207] levels completed is now: 0
2011-01-26 22:30:56.362 Practice[8809:207] dictionary values...:
2011-01-26 22:30:57.015 Practice[8809:207] key=gameProgress, value=0
May be something is wrong with your class level object "levelsCompleted", check if it is not NSNumber.
But rest looks fine ....
I need an NSDictionary which has key in the form of string (#"key1", #"key2") and value in the form of a C-style two-dimensional array (valueArray1,valueArray2) where valueArray1 is defined as :
int valueArray1[8][3] = { {25,10,65},{50,30,75},{60,45,80},{75,60,10},
{10,70,80},{90,30,80},{20,15,90},{20,20,15} };
And same for valueArray2.
My aim is given an NSString i need to fetch the corresponding two-dimensional array.
I guess using an NSArray, instead of c-style array, will work but then i cannot initialize the arrays as done above (i have many such arrays). If, however, that is doable please let me know how.
Currently the following is giving a warning "Passing argument 1 of 'dictionaryWithObjectsAndKeys:' from incompatible pointer type" :
NSDictionary *myDict = [NSDictionary dictionaryWithObjectsAndKeys:valueArray1,#"key1",
valueArray2,#"key2",nil];
Is valueArray2 also an int[][3]? If so, you could use
[NSValue valueWithPointer:valueArray1]
to convert the array into an ObjC value. To retrieve the content, you need to use
void* valuePtr = [[myDict objectForKey:#"key1"] pointerValue];
int(*valueArr)[3] = valuePtr;
// use valueArr as valueArrayX.
If there's just 2 keys, it is more efficient to use a function like
int(*getMyValueArr(NSString* key))[3] {
if ([key isEqualToString:#"key1"]) return valueArray1;
else return valueArray2;
}
Rather than Adding Array Directly as a value in NSDictionary make a custom class in which create variable of NSArray ... and set this class object as value like
NSDictionary *myDict = [NSDictionary dictionaryWithObjectsAndKeys:MyClassObj1,#"key1",
MyClassObj2,#"key2",nil];
where MyClassObj1 and MyClassObj2 are member of MyClass
I'm messing around with NSNumber for an iPhone app, and seeing what I can do with it. For most of my variables, I simple store them as "int" or "float" or whatnot. However, when I have to pass an object (Such as in a Dictionary) then I need them as an Object. I use NSNUmber. This is how I initialize the object.
NSNumber *testNum = [NSNumber numberWithInt:varMoney];
Where "varMoney" is an int I have declared earlier in the program. However, I have absolutely no idea how to get that number back...
for example:
varMoney2 = [NSNumber retrieve the variable...];
How do I get the value back from the object and set it to a regular "int" again?
Thanks!
(Out of curiosity, is there a way to store "int" directly in an Objective-C dictionary without putting it in an NSNumber first?)
You want -intValue, or one of its friends (-floatValue, -doubleValue, etc.). From the docs:
intValue Returns the receiver’s value
as an int.
- (int)intValue
Return Value The receiver’s value as
an int, converting it as necessary.
The code would be:
int varMoney2 = [testNum intValue];
NSNumber *testNum = [NSNumber numberWithInt:varMoney];
/* Then later... */
int newVarMoney = [testNum intValue];