一个可变参数函数是指一个函数拥有不定的参数,即为一个函数可接收多个参数。
在iOS中比较常见的比如NSArray中的初始化函数方法
+ (instancetype)arrayWithObjects:(ObjectType)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
其中
NS_REQUIRES_NIL_TERMINATION
,是一个宏,用于编译时非nil
结尾的检查。 调用时要以nil
结尾,否则会崩溃。
字面的意思是NS系列的需要以nil作为终止符这里由于是可变参数,所以参数的个数并不确定,所有在系统进行遍历该你传进去的参数时会进行判断是否读取到nil的终止符。当读到终止符nil时确定参数的个数停止进行遍历。
在iOS要实现不定参数的函数,有一个方案是用C/C++中的va_list、va_start、va_arg、va_end来实现。这样实现需要一个哨兵参数,就是调用方法是最后必须要加一个nil或者0的参数,该参数就称为哨兵参数。
va_list args用于声明一个变量,我们知道函数的可变参数列表其实就是一个字符串,所以va_list才被声明为字符型指针,这个类型用于**声明一个指向个数可变的参数列表的字符型指针变量。
va_start(args, param):初始化前面定义的va_list变量,让指针一开始指向首个参数。args--我们之前定义的偏移指针 param--参数列表的第一个参数。
va_arg(args, type)函数的作用是根据指针进行取值,取出值以后返回,并且指针偏移一位,所以可以进行一个循环,通过va_arg不停的移动指针,依次取出后面的参数。args---作用同上 type--参数的类型,如NSString *。
a_end(args):清空参数列表,并置参数指针args无效,结束参数的获取。
举例说明
//声明
- (void)test:(NSString *)firstParam, ... NS_REQUIRES_NIL_TERMINATION;
// 实现
// 可变参数
- (void)test:(NSString *)firstParam,... NS_REQUIRES_NIL_TERMINATION{
if (firstParam) {
// 取出第一个参数
NSLog(@"%@", firstParam);
// 定义一个指向个数可变的参数列表指针;
va_list args;
// 用于存放取出的参数
NSString *arg;
// 初始化上面定义的va_list变量,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数
va_start(args, firstParam);
// 遍历全部参数 va_arg返回可变的参数(a_arg的第二个参数是你要返回的参数的类型)
while ((arg = va_arg(args, NSString *))) {
NSLog(@"%@", arg);
}
// 清空参数列表,并置参数指针args无效
va_end(args);
}
}