可以在Obj-c中为变量参数函数发送一个数组吗?

mam*_*mcx 12 objective-c

在python中,很容易构建一个字典或数组,并将其解压缩到具有可变参数的函数

我有这个:

- (BOOL) executeUpdate:(NSString*)sql, ... {
Run Code Online (Sandbox Code Playgroud)

手动方式是这样的:

[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]];
Run Code Online (Sandbox Code Playgroud)

但我不能硬编码我正在调用的参数,我想:

NSMutableArray *values = [NSMutableArray array];

for (NSString *fieldName in props) {
  ..
  ..
  [values addObject : value]
}
[db executeUpdate:@"insert into test (a, b, c, d, e) values (?, ?, ?, ?, ?)" ,??values];
Run Code Online (Sandbox Code Playgroud)

joh*_*les 18

Chuck是对的,在Objective-C中没有正确的参数解包.但是,对于需要nil终止的方法(NS_REQUIRES_NIL_TERMINATION),可以将变量列表扩展为大于使用返回nil的数组访问器所需的变量列表index >= count.这肯定是一个黑客,但它的工作原理.

// 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
Run Code Online (Sandbox Code Playgroud)

现在,您可以NSArrayToVariableArgumentsList在任何预期的nil-terminated变量参数列表中使用(只要您的数组小于10个元素).例如:

NSArray *otherButtonTitles = @[@"button1", @"button2", @"button3"];
UIActionSheet *actionSheet = [[self alloc] initWithTitle:@"Title"
                                                delegate:self
                                       cancelButtonTitle:@"Cancel"
                                  destructiveButtonTitle:nil
                                       otherButtonTitles:NSArrayToVariableArgumentsList(otherButtonTitles)];
Run Code Online (Sandbox Code Playgroud)

  • 这样的黑客,但可爱的黑客. (2认同)

Chu*_*uck 15

很不幸的是,不行.Objective-C没有像许多现代语言中那样的参数解包.我找不到一个解决它的好方法.

问题的一部分是Objective-C本质上只是C.它使用C varargs传递多个参数,并且没有简单的方法来使用varargs.相关的SO讨论.