performSelector有两个缺陷:
1、最多只能传递两个参数
2、无法传递数值参数,如整形、浮点型等
对于第一个问题,网上有很多解决方法,百度一大堆。但第二个问题,反正我没有百度到。
经过我的探索,我在网上一段代码上进行了修改,整合如下:
- (id)performSelector:(SEL)aSelector withTheObjects:(NSArray*)objects{
//1、创建签名对象
// NSMethodSignature*signature = [self methodSignatureForSelector:aSelector];
NSMethodSignature*signature = [[self class] instanceMethodSignatureForSelector:aSelector];
//2、判断传入的方法是否存在
if (!signature) {
//传入的方法不存在 就抛异常
NSString*info = [NSString stringWithFormat:@"-[%@ %@]:unrecognized selector sent to instance",[self class],NSStringFromSelector(aSelector)];
@throw [[NSException alloc] initWithName:@"方法没有" reason:info userInfo:nil];
return nil;
}
//3、创建NSInvocation对象
NSInvocation*invocation = [NSInvocation invocationWithMethodSignature:signature];
//4、保存方法所属的对象
invocation.target = self; // index 0
invocation.selector = aSelector; // index 1
//5、设置参数
NSInteger arguments = signature.numberOfArguments -2;
NSUInteger objectsCount = objects.count;
NSInteger count = MIN(arguments, objectsCount);
[self setInv:invocation andArgs:objects argsCount:count];
//6、调用NSinvocation对象
[invocation invoke];
//7、获取返回值
id res = nil;
if (signature.methodReturnLength ==0) return nil;
//getReturnValue获取返回值
[invocation getReturnValue:&res];
return res;
}
- (void)setInv:(NSInvocation *)inv andArgs:(NSArray *)args argsCount:(NSUInteger)count{
for (int i = 0; i<count; i++) {
NSObject*obj = args[i];
//处理参数是NULL类型的情况
if ([obj isKindOfClass:[NSNull class]]) {
obj = nil;
}
//对整形数值等的处理
if([obj isKindOfClass:[NSNumber class]]) //对数值数据的处理
{
void *p;
NSNumber *num = (NSNumber *)obj;
if(strcmp([num objCType], @encode(float)) == 0)
{
float v = [num floatValue];
p = &v;
}
else if(strcmp([num objCType], @encode(double)) == 0)
{
double v = [num doubleValue];
p = &v;
}
else
{
long v = [num longValue];
p = &v;
}
[inv setArgument:p atIndex:i+2];
continue;
}
[inv setArgument:&obj atIndex:i+2];
}
}
其实没改动什么,就加了下面这段代码:
//对整形数值等的处理
if([obj isKindOfClass:[NSNumber class]]) //对数值数据的处理
{
void *p;
NSNumber *num = (NSNumber *)obj;
if(strcmp([num objCType], @encode(float)) == 0)
{
float v = [num floatValue];
p = &v;
}
else if(strcmp([num objCType], @encode(double)) == 0)
{
double v = [num doubleValue];
p = &v;
}
else
{
long v = [num longValue];
p = &v;
}
[inv setArgument:p atIndex:i+2];
return;
}
使用:
上面是NSObject的类别,传整形数值:
[_bledataMana performSelector:@selector(sendMsg:)withTheObjects:@[@10]];