一、可变参数是什么
想定义一个方法,但是不知道以后要用的时候想传几个参数进去,最经典的例子就是UIAlertView
的构造方法
在 Objective-C 中:
- (instancetype)initWithTitle:(nullable NSString *)title message:(nullable NSString *)message delegate:(nullable id /*<UIAlertViewDelegate>*/)delegate cancelButtonTitle:(nullable NSString *)cancelButtonTitle otherButtonTitles:(nullable NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION
在 Swift 中:
public convenience init(title: String, message: String, delegate: UIAlertViewDelegate?, cancelButtonTitle: String?, otherButtonTitles firstButtonTitle: String, _ moreButtonTitles: String...)
下面我将分别用 Objective-C 和 Swift 实现。
二、Objective-C 实现可变参数
首先必须了解各个宏的功能是什么:
-
NS_REQUIRES_NIL_TERMINATION
:是一个宏,用于编译时非nil结尾的检查。 调用时要以nil结尾,否则会崩溃。 -
va_list
:用于声明一个变量,函数的可变参数列表其实就是一个字符串,所以va_list才被声明为字符型指针,这个类型用于声明一个指向参数列表的字符型指针变量,例如:va_list ap; //ap:arguement pointer
-
va_start(ap,v)
:它的第一个参数是指向可变参数字符串的变量,第二个参数是可变参数函数的第一个参数,通常用于指定可变参数列表中参数的个数。 -
va_arg(ap,t)
:它的第一个参数指向可变参数字符串的变量,第二个参数是可变参数的类型。 -
va_end(ap)
:用于将存放可变参数字符串的变量清空(赋值为NULL)。
// .h文件中
- (NSString *)addMoreArguments:(NSString *)firstStr,...NS_REQUIRES_NIL_TERMINATION;
// .m文件中
- (NSString *)addMoreArguments:(NSString *)firstStr,...
{
//定义一个指向个数可变的参数列表指针
va_list args;
// 获取第一个可选参数的地址.使参数列表指针指向函数参数列表中的第一个可选参数
va_start(args, firstStr);
NSMutableString *allStr = [NSMutableString string];
// 遍历参数,直到等于nil时结束
for (NSString *str = firstStr; str != nil; str = va_arg(args, NSString *)) {
[allStr appendFormat:@"%@",str];
}
// 清空参数列表,并置参数指针args无效
va_end(args);
return allStr;
}
三、Swift 实现可变参数
Swift 的实现比 Objective-C 简单太多太多:
func addMoreArguments(firstStr: String...) {
var result = String()
// 遍历参数
for str in firstStr {
result += str
}
print(result)
}
这是用 Swift 实现与 Objective-C 完全相同功能的代码,哪个简单?不言而喻~~