method with many parameters - iphone

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

Related

Saving enum values into a dictionary

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.

How can I pass a property of a class as a parameter of a method in objective-c

How can I pass a property of a class as a parameter of a method in objective-c?
So as an example assume I have:
a CoreData managed object class MyData with dynamic properties PropA, PropB, PropC all of the same type
I have a utils method that will perform calculations and update one of these properties, which takes as input the MyData instance
how can I arrange so the utils method can accept an indication of which property to use in the calculations and updating? (e.g. PropB)
So then need:
A way to pass an indication of the property to the method (e.g. send as String?)
A way in the method to take this (from 1 above) and use this to both (a) access the value of this property in the MyData instance the method has, PLUS (b) update the property too.
A properties will have setter and getter method. In you case, I assume there are setPropA, setPropB, setPropC for setters and PropA, PropB, PropC for getters.
Then I pass string "PropA" to util, indicate I want to access property named PropA.
The util can get the value by
id val = [aObj performSelector:NSSelectorFromString(#"PropA")];
And set the property by
[aObj performSelector:NSSelectorFromString(#"SetPropA") withObject:newValue];
Or, You can pass setter and getter as parameter by NSStringFromSelector(), turn selector into a NSString. For example, I pass setter and getter by NSDictionary.
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
NSStringFromSelector(#selector(setPropA:)), kSetterKey,
NSStringFromSelector(#selector(PropA)), kGetterKey, nil];
// inside myUtil
NSString *setter = [userInfo objectForKey:kSetterKey];
[aObj performSelector:NSSelectorFromString(setter) withObject:newValue];
NSString *getter = [userInfo objectForKey:kGetterKey];
id val = [aObj performSelector:NSSelectorFromString(getter)];
Hope this helps.
Yes, you can pass the property name as a String.
Then you can access the indicated property via Key-Value Coding:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html
Example:
- (void) myUtilMethod: (MyData *) myData
forPropertyNamed: (NSString *) propName /* which property to operate on (1) */
{
id oldValue = [ myData valueForKey: propName]; // get value (2a)
id newValue = ...; // your calculation here
[myData setValue: newValue forKey: propName]; // set value (2b)
}
I won't bind the 2 classes directly. You should set up a pattern design that allows you to loosely couple them together by creating a class that will do the interface between those two.

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

Obj-C: Difference between "Fairfield" and #"Fairfield" (with at string)?

I just had a ridonkulous typo in my iPhone app, answered here.
Now I'm wondering about the #"..." notation.
why this works:
NSArray *someArray = [NSArray arrayWithObjects: #"Fairfield", nil];
and this does not (even though it compiles, it will throw an EXC_BAD_ACCESS):
NSArray *someArray = [NSArray arrayWithObjects: "#Fairfield", nil];
Edit:
Ok, so you guys have pointed out that I can't add a C string to an NSArray, because it's obviously not an object.
Now another question: Isn't this somewhat of an oversight? I mean, why does the "...WithObjects:" message specify a list of (id) instead of (NSObject *)?
"#Fairfield" is a normal C string with an '#' character in it. #"Fairfield" is an Objective-C string (NSString on OS X) with no literal '#' in it.
You cannot add C strings to Cocoa collections.
It accepts id rather than NSObject because all initialisers return id. All initialisers return id because subclasses would otherwise override the return type of their ancestors' initialisers.
For example, -[NSMutableString init] can't return NSMutableString * because it subclasses -[NSString init], which can't return NSString * because it overrides -[NSObject init].
Unfortunately, implicit type-casting between const char * and id is perfectly legit, so the compiler won't throw a warning, however a static analyser may be able to pick this sort of mishap up fairly easily.
"Fairfield" is a C string, #"Fairfield" is an Objective-C string.
#"Fairfield" is an object (NSString), so you can send it methods ([#"Fairfield" uppercaseString]) and add it to Objective-C arrays ([NSArray arrayWithObjects:#"Fairfield",nil]). You can only add objects to NSArrays.
On the other hand, "Fairfield" is a C string, and is generally not used in Cocoa. For the most part, you can get by with only using #"Fairfield"
The other reason that a number of things in Cocoa deal with id rather than NSObject* is because, unlike some other languages (say, Java and C#), where all objects in the language must inherit from some global base class, it's entirely possible to have objects that do not descend from NSObject (NSProxy being one example). It's not something you'd do often, but it is possible. The id type means "pointer to any Objective C instance".