在ARC中伪造va_list

我需要在iOS应用程序中创build一个虚拟的va_list传递给一个NSString的initWithFormat:arguments: function,这是我的代码:

 NSArray *fixedArguments = [[NSArray alloc] initWithArray:arguments]; NSRange range = NSMakeRange(0, [fixedArguments count]); va_list fakeArgList = (va_list)malloc(sizeof(NSString *) * [fixedArguments count]); __unsafe_unretained id *ptr = (__unsafe_unretained id *)fakeArgList; [fixedArguments getObjects:ptr range:range]; content = [[NSString alloc] initWithFormat:outputFormat arguments:(va_list)fakeArgList]; free(fakeArgList); 

编译器会在cast行上抱怨这条消息:

 error: cast of a non-Objective-C pointer type 'va_list' (aka 'char *') to '__unsafe_unretained id *' is disallowed with ARC 

getObjects:range:函数的定义如下:

 - (void)getObjects:(id __unsafe_unretained [])objects range:(NSRange)range; 

我已经尝试了一切,但仍然无法摆脱这个错误…

是否有一个解决scheme,创build一个虚拟的va_list启用ARC? 我究竟做错了什么?

编辑:这不再工作。 正如在最初的答案中所预见的那样,ABI似乎已经从这个答案中改变了出来

玩了一下,并得到它的工作 – 双检查泄漏或遗弃的记忆,没有看到任何。

  NSArray *fixedArguments = [[NSArray alloc] initWithObjects: @"foo", @"bar", @"baz", nil]; NSRange range = NSMakeRange(0, [fixedArguments count]); NSMutableData* data = [NSMutableData dataWithLength: sizeof(id) * [fixedArguments count]]; [fixedArguments getObjects: (__unsafe_unretained id *)data.mutableBytes range:range]; NSString* content = [[NSString alloc] initWithFormat: @"1: %@ 2: %@ 3: %@" arguments: data.mutableBytes]; NSLog(@"%@", content); 

我喜欢(AB)像这样使用NSMutableData来获得保留/释放语义在任意一块内存上 – 这不一定与手头上的问题有关,但它是一个巧妙的小技巧。

作为未来读者的一个注意事项:像这样伪装va_list恰好适用于MacOS和iOS的当前ABI,但总的来说它不是可移植的,并不是一个好的方法。

如果你愿意为你的项目添加一点点快捷的话,这是可能的!

重要的是NSArray到[CVarArgType]的映射,这是va_list的快速等价物。 如果尝试将[AnyObject][CVarArgType]则会导致运行时崩溃,但通过map我们可以明确地创build所需的列表。

其余的代码是我做的包装器,以便我可以从obj-c调用它。 你可以使用这种方式来调用任何你想调用的obj-c函数的包装。

 @objc class StringFormat: NSObject { class func format(key: String, args: [AnyObject]) -> String { let locArgs: [CVarArgType] = args.map({ (arg: AnyObject) -> CVarArgType in if let iArg = (arg is NSNumber ? arg.intValue : nil) { return iArg } return arg as! CVarArgType }); return String(format: key, arguments: locArgs) } } 
Interesting Posts