廢話少說,直接上代碼。
函數實現
- (void)doSomethingWithItems:(NSObject *)obj1, ... {
va_list args;
va_start(args, obj1);
NSObject *item;
while (item = va_arg(args, NSObject *)) {
// do something
}
}
// 函數調用
- (void)method {
NSObject *param1 = [NSObject alloc] init];
NSObject *param2 = [NSObject alloc] init];
NSObject *param3 = [NSObject alloc] init];
[xxx doSomethingWithItems:param1, param2, param3];
}
執行,exc_bad_access
崩潰。
把調用改成:
- (void)method {
NSObject *param1 = [NSObject alloc] init];
NSObject *param2 = [NSObject alloc] init];
NSObject *param3 = [NSObject alloc] init];
[xxx doSomethingWithItems:param1, param2, param3, nil];
}
不崩潰。
可變長參數需要明確指定結尾,不然會野指針。
如果在每次調用的地方都手動增加nil
很蠢。
高級方法是在函數定義的地方增加哨兵宏NS_REQUIRES_NIL_TERMINATION
- (void)doSomethingWithItems:(NSObject *)obj1, ... NS_REQUIRES_NIL_TERMINATION
此時調用該方法會自動補全nil
。
在
NSArray
的初始化方法中有這種用法
+ (instancetype)arrayWithObjects:(ObjectType)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
但是在NSString
的可變長初始化方法中確沒有哨兵宏+ (instancetype)stringWithFormat:(NSString *)format, ...
那是因為在format
參數中已經明確指定了參數的個數。如果我們不想使用哨兵宏也可以在方法的第一個參數中指定個數。
歡迎關注微信公眾號查看更多高質量文章:愛編程的大頭