Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is possible send a array in Obj-c for a variable arguments function?

Tags:

objective-c

In python it is easy to build a dictionary or array and pass it unpacked to a function with variable parameters

I have this:

- (BOOL) executeUpdate:(NSString*)sql, ... {

And the manual way is this:

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

But I can't hardcode the parameters I'm calling, I want:

NSMutableArray *values = [NSMutableArray array];

for (NSString *fieldName in props) {
  ..
  ..
  [values addObject : value]
}
[db executeUpdate:@"insert into test (a, b, c, d, e) values (?, ?, ?, ?, ?)" ,??values];
like image 447
mamcx Avatar asked Jan 10 '09 22:01

mamcx


1 Answers

Chuck is right, there's no proper argument unpacking in Objective-C. However, for methods that require nil termination (NS_REQUIRES_NIL_TERMINATION), you can expand the variable list larger than what is needed by using an array accessor that returns nil when index >= count. This is most certainly a hack, but it works.

// Return nil when __INDEX__ is beyond the bounds of the array
#define NSArrayObjectMaybeNil(__ARRAY__, __INDEX__) ((__INDEX__ >= [__ARRAY__ count]) ? nil : [__ARRAY__ objectAtIndex:__INDEX__])

// Manually expand an array into an argument list
#define NSArrayToVariableArgumentsList(__ARRAYNAME__)\
NSArrayObjectMaybeNil(__ARRAYNAME__, 0),\
NSArrayObjectMaybeNil(__ARRAYNAME__, 1),\
NSArrayObjectMaybeNil(__ARRAYNAME__, 2),\
NSArrayObjectMaybeNil(__ARRAYNAME__, 3),\
NSArrayObjectMaybeNil(__ARRAYNAME__, 4),\
NSArrayObjectMaybeNil(__ARRAYNAME__, 5),\
NSArrayObjectMaybeNil(__ARRAYNAME__, 6),\
NSArrayObjectMaybeNil(__ARRAYNAME__, 7),\
NSArrayObjectMaybeNil(__ARRAYNAME__, 8),\
NSArrayObjectMaybeNil(__ARRAYNAME__, 9),\
nil

Now you can use NSArrayToVariableArgumentsList wherever you expect a nil-terminated variable argument list (as long as your array is smaller than 10 elements). For example:

NSArray *otherButtonTitles = @[@"button1", @"button2", @"button3"];
UIActionSheet *actionSheet = [[self alloc] initWithTitle:@"Title"
                                                delegate:self
                                       cancelButtonTitle:@"Cancel"
                                  destructiveButtonTitle:nil
                                       otherButtonTitles:NSArrayToVariableArgumentsList(otherButtonTitles)];
like image 121
johnboiles Avatar answered Nov 15 '22 22:11

johnboiles