Is there a way to pass NSArray to a method that expects a variable number of arguments, for example + stringWithFormat:

In some context: I'm trying to clear part of my FMDB code. My table has many columns, and the method in FMDB that I need to use is the one that expects a variable number of arguments, similar to the method of the NSString +stringWithFormat: class.

Example:

 [db executeUpdate:@"insert into test (a, b, c, d, e) values (?, ?, ?, ?, ?)" , @"hi'", // look! I put in a ', and I'm not escaping it! [NSString stringWithFormat:@"number %d", i], [NSNumber numberWithInt:i], [NSDate date], [NSNumber numberWithFloat:2.2f]]; 

When a table has only 5 columns, it is not so bad, but when a column has 20+, it starts to become hairy.

I would like to create a dictionary with all the information about db abstraction and dynamically build these queries. My question is ... How do I fake this method in Objective-C by expecting a variable number of arguments and, instead, maybe pass it an NSArray?

Additional Information:

How to write a method that takes a variable number of arguments, for example NSString + stringWithFormat :?

+4
source share
4 answers

(Edit: this worked in the days of GCC. It does not apply to Clang with Xcode 4.6.)


Get the objects in the array into the C array, and then consider this as a list of varargs:

 //The example input array int i = 42; NSArray *array = [NSArray arrayWithObjects: [NSString stringWithFormat:@"number %d", i], [NSNumber numberWithInt:i], [NSDate date], [NSNumber numberWithFloat:2.2f], nil]; //The example destination (using NSString so anyone can test this) NSString *string = nil; //The intermediary C array NSObject **arrayObjects = malloc(sizeof(NSObject *) * [array count]); if (arrayObjects) { //Fill out the C array. [array getObjects:arrayObjects]; //Use the C array as a va_list. string = [[[NSString alloc] initWithFormat:@"%@ %@ %@ %@" arguments:(va_list)arrayObjects] autorelease]; free(arrayObjects); } NSLog(@"string: %@", string); 

Output:

 2009-03-26 20:10:07.128 NSArray-varargs[606:10b] string: number 42 42 2009-03-26 20:10:07 -0700 2.2 

In your case, you will use the method -[FMDatabase executeUpdate:arguments:] .

+6
source

It may be easier to simply create a category in FMDatabase that takes an array and performs updates. You should be able to copy most of executeUpdate to do this.

+4
source

I think NSInvocation can do what you want to do.

Just be careful when calling setArgumentForIndex, because args 0 and 1 are implicit, which Obj-C fills in, where arg 2 is the first "real" argument you pass.

+1
source

This may not be the example you are looking for. But in this case, I would put your string values ​​in an array, and then use [theArray componentsJoinedByString: @ ","] to turn them into your list of sql arguments.

0
source

All Articles