NSString*result1 = [selfappend:@"a"withStr2:@"b"andStr3:@"c"];
//这种方式调用方法最多只能传递两个参数 运行时系统负责去找方法 在编译的时候不做任何校验 如果直接调用(如上)会做校验
NSString*result2 = [selfperformSelector:@selector(append:withStr2:andStr3:)withObject:@"a"withObject:@"b"];
NSLog(@"result1 = %@\nresult2 = %@",result1,result2);
NSString *methodNameStr = @"append:withStr2:andStr3:";
// NSInvocation 使用
//c创建一个方法签名
SELselector =NSSelectorFromString(methodNameStr);
//上面的两个方法中,aSelector参数,不一定是你要调用的那个方法,可以是任意方法,但是该方法的参数个数必须与你要调用的参数个数一致
NSMethodSignature*signature = [selfmethodSignatureForSelector:selector];
//或者使用下面方式
// NSMethodSignature *signature2 = [[self class]instanceMethodSignatureForSelector:selector];
// signature.numberOfArguments// 方法参数的个数
// signature.methodReturnLength 方法返回值类型的长度,大于0表示有返回值
//使用方法签名创建一个NSInvocation对象
NSInvocation*invocation = [NSInvocationinvocationWithMethodSignature:signature];
//设置NSInvocation 的tage selector 表示要执行谁的(tage)那个方法(selector)
[invocationsetTarget:self];
[invocationsetSelector:selector];
/*给要执行的方法设置参数 使用
[invocation setArgument:<#(nonnull void *)#> atIndex:<#(NSInteger)#>]
给要执行的方法设置参数 ⚠️下标应该从2开始,因为0和1已经被target于selector占用
设置参数必须传递参数地址,不能直接穿值
*/
NSString*arg1 =@"a";
NSString*arg2 =@"b";
NSString*arg3 =@"c";
[invocationsetArgument:&arg1atIndex:2];
[invocationsetArgument:&arg2atIndex:3];
[invocationsetArgument:&arg3atIndex:4];
//执行方法
[invocationinvoke];
如果方法没有返回值可以把这个判断去掉
if(signature.methodReturnLength>0) {
/*
返回值为对象时,arc情况下容易出现崩溃问题,arc下vc如果用strong的,默认NSInvocation实现认为,已经对返回对象retain一次,实际上并没有,当返回对象出了作用域的时候就被收回,导致崩溃 返回值加个__weak 就可以了
*/
__weakNSString*result =nil;
[invocationgetReturnValue:&result];
NSLog(@"获得的返回值%@",result);
}
- (NSString*)append:(NSString*)str1 withStr2:(NSString*)str2 andStr3:(NSString*)str3{
NSString*str = [str1stringByAppendingString:str2];
str = [strstringByAppendingString:str3];
return str;
}
网友评论