《iOS软件开发揭密》的笔记-第89页
可变参数在Objective-C中用 “, ... ” 表示
在示例代码中,如此接收变参:
- + (NSInvocation*)invocationWithTarget:(id)_target andSelector:(SEL)_selector andArguments:(void*)_addressOfFirstArgument, ...
- {
- NSMethodSignature* methodSig = [_target methodSignatureForSelector:_selector];
- NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:methodSig];
- [invocation setTarget:_target];
- [invocation setSelector:_selector];
- unsigned int numArgs = [methodSig numberOfArguments];
- if (2 < numArgs)
- {
- va_list varargs;
- va_start(varargs, _addressOfFirstArgument);
- [invocation setArgument:_addressOfFirstArgument atIndex:2];
- for (int argIdx=3; argIdx<numArgs; ++argIdx)
- {
-
- void* argp = va_arg(varargs, void *);
- [invocation setArgument:argp atIndex:argIdx];
- }
-
- va_end(varargs);
- }
- return invocation;
- }
1、对这个va_list类型很是好奇,Jump to Definition定位到了stdarg.h文件,发现如下定义:
- #ifndef _VA_LIST
- typedef __builtin_va_list va_list;
- #define _VA_LIST
- #endif
- #define va_start(ap, param) __builtin_va_start(ap, param)
- #define va_end(ap) __builtin_va_end(ap)
- #define va_arg(ap, type) __builtin_va_arg(ap, type)
这个__builtin_va_list 据说是gcc编译器内置的宏,针对不同平台,数据类型和字长可能不同。
2、setArgument 动态织入参数 atIndex 为2,为什么是从2开始呢?
IOS Developer Libraray(https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/Reference/Reference.html)给出这样的解释:
“Indices 0 and 1 indicate the hidden arguments self and _cmd, respectively; ”
原来,第1参数隐式为对象自身(id),第2参数隐式为方法体(SEL)