Saving enum values into a dictionary - iphone

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.

Related

method with many parameters

i have a method with 20 parameters,( NSString, float,....), can i construct a type ( for example Enumerated, typdef) to invoque my method and not pass all my parameters ?
replace:
-(void)myMethodeParam1:...:param2:.... ;
with:
-(void)myMethode:MyNewTypeParam ;
tanks for your answers
You can use NSDictionary (NSMutableDictionary). You'll need to wrap primitive type (like float) to obj-c objects (e.g. NSNumber) for that though.
E.g. you have 10 NSString params named param0,...,param9 then you can place them in NSDictionary:
NSDictionary *paramDict = [NSDictionary dictionaryWithObjectsAndKeys:string0, #"param0", string1, #"param1", ..., string9, #"param9", nil];
[obj myMethod: paramDict];
or if you can enumerate your variables somehow you can use NSMutableDictionary and add them to it in a loop.
Then in your method you can get your parameters from dictionary you have:
-(void)myMethode: (NSDictionary*)dict{
NSString *string0 = [dict objectForKey:#"param0];
//Do something with it
...
}
If your parameters together are some logical entity and they're usually used together you also can also create a custom class that contains them as instance variables

NSDictionary with integer as number

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];

NSDictionary with key => String and Value => c-Style array

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

What kind of data is in an "enum" type constant? How to add it to an NSArray?

What kind of information is stored behind such an enum type thing? Example:
typedef enum {
UIViewAnimationCurveEaseInOut,
UIViewAnimationCurveEaseIn,
UIViewAnimationCurveEaseOut,
UIViewAnimationCurveLinear
} UIViewAnimationCurve;
I am not sure if I can safely add such an enum constant to an array. Any idea?
Enums in Objective-C are exactly the same as those in C. Each item in your enum is automatically given an integer value, by default starting with zero.
For the example you provided: UIViewAnimationCurveEaseInOut would be 0; UIViewAnimationCurveEaseIn would be 1, and so on.
You can specify the value for the enum if required:
typedef enum {
UIViewAnimationCurveEaseInOut,
UIViewAnimationCurveEaseIn = 0,
UIViewAnimationCurveEaseOut,
UIViewAnimationCurveLinear
} UIViewAnimationCurve;
This result of this would be: UIViewAnimationCurveEaseInOut is 0; UIViewAnimationCurveEaseIn is 0; UIViewAnimationCurveEaseOut is 1; and so on. However, for basic purposes you shouldn't need to do anything like that; it just gives you some useful info to toy with.
It should be noted based on the above, that an enum can't assume to be a unique value; different enum identifiers can be equal in value to each other.
Adding an enum item to a NSArray is as simple as adding an integer. The only difference would be that you use the enum identifer instead.
[myArray addObject:[NSNumber numberWithInt:UIViewAnimationCurveEaseInOut]];
You can check this out for yourself by simply outputting each enum to the console and checking the value it provides you with. This gives you the opportunity to investigate the details of how it operates. But for the most part you won't really need to know on a day to day basis.
Enums are typically int values. You can store them in an array by wrapping them in an NSNumber:
[myMutableArray addObject:[NSNumber numberWithInt:myAnimationCurve]];
... then get them back out like this:
UIViewAnimationCurve myAnimationCurve = [[myMutableArray lastObject] intValue];
Enums in Objective-C are the same as enums in vanilla C. It's just an int. If you're using an NSArray, then it expects a pointer and you'll get a warning if you try to add an int to it:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
[myArray addObject:UIViewAnimationCurveEaseInOut];
// Last line results in:
// warning: passing argument 1 of 'addObject:' makes
// pointer from integer without a cast
If you're storing a large collection of 32-bit integers, consider using the appropriate CF collection type rather than the NS collection type. These allow you to pass in custom retain methods, which gets rid of the need to box every integer added to the collection.
For example, let's say you want a straight array of 32-bit ints. Use:
CFMutableArrayRef arrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
The last parameter tells the array to not retain/release the "addresses" you pass in to it. So when you do something like this:
CFArrayAppendValue(arrayRef, 1);
What the array thinks is that you're passing in a pointer to an object living at the memory address 0x1. But since you told it to not call retain/release on that pointer, it gets treated as a standard int by the collection.
FWIW, for educational value, standard NSMutableArrays have equivalent CF types. Through toll-free bridging you can use the CF collection as a standard Foundation collection:
CFMutableArrayRef arrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, kCFTypeArrayCallbacks);
NSMutableArray *array = (NSMutableArray *)arrayRef;
[array addObject:#"hi there!"];
NSLog(#"%#", [array objectAtIndex:0]); // prints "hi there!"
You can apply the same tricks to dictionaries (with CFDictionary/CFMutableDictionary), sets (CFSet/CFMutableSet), etc.

NSNumber, Setting and Retrieving

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];