所以我在C中有一个函数
#define PRINTF(format) { va_list list; va_start(list, format); vprintf(format, list);}
void foo(const char* format, ...) {
PRINTF(format)
}
我想知道我是否要将Swift等同于上面的代码,我将如何代表......作为?我知道如何使用变量参数的唯一方法是使用CVarArgType,或使用参数数组。
但是,由于这个C片段使用了一个宏,我发现很难将这个代码移植到Swift而不改变我所做的函数的参数而不是宏。关于如何做这样的事情,我能获得任何见解或帮助吗?
我需要帮助在Swift中编写#define宏等效函数,并且在提供等效于va_list列表,va_start调用时遇到问题。
答案 0 :(得分:2)
好吧,我原来的答案绝对让事情过于复杂......
我们做需要String
为格式,CVarArgType...
为参数列表(在{1}}内被视为[CVarArgType]
功能)。我试图使用Objective-C NSString
来复杂化它。如果我们坚持使用Swift的String
,它实际上有一个初始化器,它接受我们传递的参数。
在Swift中编写此函数的最简单的方式如下所示:
func foo(format: String, args: CVarArgType...) {
println(String(format: format, arguments: args))
}
据我所知, Swift不允许使用#define
宏。但是,我们可以将该C宏转换为常规的Swift函数。
func foo(format: String, args: CVarArgType...) {
println(NSString(format: format, arguments: getVaList(args)))
}
CVarArgType
是一个Swift协议,它接受我们通常传入String的格式字符串。
...
使函数接受最后一个参数的任意数量的参数。在函数中,它将具有类型[CVarArgType]
(数组)。
同时,NSString
的初始值设定项(以及类似的NSLog
和其他类似的点)正在寻找CVaListPointer
作为最后一个参数,因此我们可以使用Swift的内置函数,getVaList
,将[CVarArgType]
转换为CVaListPointer
。
可以这样调用此函数:
foo("%@, %@... %i", "hello", "world", 123)
将打印:
hello, world... 123
正如@AirspeedVelocity指出的那样,通常建议使用withVaList
而不是getVaList
。我们可以这样做:
func foo(format: String, args: CVarArgType...) {
func buildLogString(argList: CVaListPointer) -> String {
return NSString(format: format, arguments: argList) as String
}
println(withVaList(args, buildLogString))
}
对于超出此特定示例的应用程序,请务必注意我们可以使用...
接受任何类型的参数列表,并且在函数内,我们得到一个数组那种类型。
例如:
func bar(myVariadicListOfStuff: MyStuffClass...) {
// myVariadicListOfStuff is a [MyStuffClass]
for thing in myVariadicListOfStuff {
// this is a MyStuffClass
}
}