Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to pass an NSArray to a method that expects a variable number of arguments, such as +stringWithFormat:

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

An 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 only has 5 columns it's not that bad but when a column has 20+ it starts to get hairy.

What I'd like to do is create a dictionary with all db abstraction information and build these queries dynamically. My question is... How in Objective-C do I fake out that method expecting a variable number of arguments and instead perhaps hand it an NSArray?

Related info:

How can I write a method that takes a variable number of arguments, like NSString's +stringWithFormat:?

like image 745
zorn Avatar asked Dec 22 '22 12:12

zorn


1 Answers

(Edit: This worked back in the GCC days. It doesn't under Clang as of Xcode 4.6.)


Get the objects in the array into a C array, then treat that as a varargs list:

//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'll use the -[FMDatabase executeUpdate:arguments:] method.

like image 145
Peter Hosey Avatar answered May 20 '23 05:05

Peter Hosey