80_iOS干货43_调用OC方法传递多个参数的11种方法

一,方法中写多个参数调用

- (void)test1 {
    [self testFunctionWithParams1:6 :@"234131#"];
}
- (void)testFunctionWithParams1:(int )number :(NSString *)string {
    NSLog(@"方法多个参数:%i%@",number, string);
}

二,performSelector调用方法

#pragma mark -  2,performSelector传参数:最多两个参数
- (void)test2 {
    [self performSelector:@selector(testFunctionWithParams1::) withObject:@5 withObject:@"67"];
    
//    动态加载方法:需要对指针做处理,最多两个参数
//    SEL selector = NSSelectorFromString(@"testFunctionWithParams2::");
//    IMP imp = [self methodForSelector:selector];
//    void (*func)(id, SEL) = (void *)imp;
//    if([self respondsToSelector:selector]){
//        func(self,selector);
//    };
    
//    也可以采用延时,但只能传一个参数
//    SEL selector = NSSelectorFromString(@"testFunctionWithParams2:");
//    [self performSelector:selector withObject:@"tom" afterDelay:0.1f];
}
- (void)testFunctionWithParams:(NSString *)string {
     NSLog(@"performSelector传参数:%@", string);
}

- (void)testFunctionWithParams2:(int )number :(NSString *)string {
     NSLog(@"performSelector传参数:%i%@",number, string);
}

三,传字典,封装成对象

#pragma mark -  3,传字典
- (void)test3 {
    //封装参数
    NSDictionary *dic = @{@"param1":@"this is a string",@"param2":@[@2,@3,@3],@"param3":@123};
    //调用方法
    [self testFunctionWithParams3:dic];
    
}
- (void)testFunctionWithParams3:(NSDictionary *)paramDic {
    NSLog(@"传字典:%@", paramDic);
}

四,传结构体,不同类型的参数

#pragma mark - 4,传结构体
- (void)test4 {
    //传结构体
    testStruct testS = {10000, @"1234"};
    [self testFunctionWithParams4:testS];
    
}
- (void)testFunctionWithParams4:(testStruct )paramStruct {
   
    NSLog(@"结构体元素aaa = %d",paramStruct.aaa);
    NSLog(@"结构体元素bbb = %@",paramStruct.bbb);
}

五,传结构体字典

#pragma mark -  5,传结构体字典
- (void)test5 {
    //传结构体
    testStruct testS = {10000, @"1234"};
    NSValue *value = [NSValue valueWithBytes:&testS objCType:@encode(testStruct)];
    //dic
    NSDictionary *dataDic = @{@"param1":@"ssfs",@"param2":@[@333,@32343],@"param3":value};
    [self testFunctionWithParams5:dataDic];
    
    
}
- (void)testFunctionWithParams5:(NSDictionary *)paramDic {
    NSLog(@"结构体字典:%@", paramDic);
    NSValue *paramValue = paramDic[@"param3"];
    testStruct paramStrout;
    [paramValue getValue:&paramStrout];
    NSLog(@"结构体字典的元素aaa:%d",paramStrout.aaa);
    
}

六,传模型

#pragma mark - 6,传模型
- (void)test6 {
    
    Parameter1 *parameter1 = [Parameter1 new];
    parameter1.number = 14;
    ParameterManager<Parameter1 *> *manager1 = [ParameterManager new];
    manager1.parameter = parameter1;
    [manager1 getParaWithType:MethodType1];
    
}

七,传指针列表,参数个数不定,但类型一致

#pragma mark -  7,传指针列表,参数个数不定,但类型一致
- (void)test7 {
    
    /*2,传同一类型的参数,个数不定 */
    [ParameterManager getType:MethodType0 params:@"23",@"389",@"889",nil];
}

//工具类中的方法实现
/*iOS实现传递不定长的多个参数的方法是使用va_list。va_list是C语言提供的处理变长参数的一种方法。在调用的时候要在参 数结尾的时候加nil
 va_list的使用需要注意:
 1.首先在函数里定义va_list型的变量,这个变量是指向参数的指针;
 2.然后用va_start初始化刚定义的va_list变量;
 3.然后用va_arg返回可变的参数,va_arg的第二个参数是你要返回的参数的类型.如果函数有多个可变参数的,依次调用va_arg获取各个参数;
 4.最后用va_end宏结束可变参数的获取
 NS_REQUIRES_NIL_TERMINATION,是一个宏,用于编译时非nil结尾的检查。 调用时要以nil结尾,否则会崩溃。
 
 */
+ (void)getType:(MethodType)mathod params:(NSString *)string, ...NS_REQUIRES_NIL_TERMINATION {
    
// 1,取出第一个参数
    NSLog(@"传的第1个参数%@", string);
    
// 2.定义一个指向个数可变的参数列表指针;
    va_list args;
    
// 3.va_start(args, str);string为第一个参数,也就是最右边的已知参数,这里就是获取第一个可选参数的地址.使参数列表指针指向函数参数列表中的第一个可选参数,函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的。
    va_start(args, string);
    
    if (string)
    {
        //依次取得除第一个参数以外的参数
// 4.va_arg(args,NSString):返回参数列表中指针所指的参数,返回类型为NSString,并使参数指针指向参数列表中下一个参数。
        // 用于存放取出的参数
        NSString *arg;
        while ((arg = va_arg(args, NSString *)))
        {
            NSLog(@"传的剩余参数有:%@",arg);
        };
    }
    //5.清空参数列表,并置参数指针args无效。
    va_end(args);
}

八,runTime的objc_msgSend传值

#pragma mark -  8,runTime的objc_msgSend传值
- (void)test8 {
    
//    ((void (*)(id, SEL))objc_msgSend)(self, @selector(test7)); //正确写法
    
    ((void (*)(id,SEL,NSString *, NSArray *, NSInteger)) objc_msgSend) (self, @selector(textFunctionWithParam8:param2:param3:),@"111",@[@2,@3],123);

}

//有三个参数的方法
-(void)textFunctionWithParam8:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 {
    NSLog(@"param1:%@, param2:%@, param3:%ld",param1, param2, param3);
}

九,NSInvocation传值

#pragma mark -  9,NSInvocation传值
- (void)test9 {
    NSArray *paramArray = @[@"112",@[@2,@13],@12];
    [self performNewSelector:@selector(textFunctionWithParam9:param2:param3:) withObjects:paramArray];
    
}
//可以传多个参数的方法
- (id)performNewSelector:(SEL)selector withObjects:(NSArray *)objects
{
    // 方法签名(方法的描述)
    NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
    if (signature == nil) {
        
        //可以抛出异常也可以不操作。
    }
    
    // NSInvocation : 利用一个NSInvocation对象包装一次方法调用(方法调用者、方法名、方法参数、方法返回值)
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    invocation.target = self;
    invocation.selector = selector;
    
    // 设置参数
    NSInteger paramsCount = signature.numberOfArguments - 2; // 除self、_cmd以外的参数个数
    paramsCount = MIN(paramsCount, objects.count);
    for (NSInteger i = 0; i < paramsCount; i++) {
        id object = objects[i];
        if ([object isKindOfClass:[NSNull class]]) continue;
        [invocation setArgument:&object atIndex:i + 2];
    }
    
    // 调用方法
    [invocation invoke];
    
    // 获取返回值
    id returnValue = nil;
    if (signature.methodReturnLength) { // 有返回值类型,才去获得返回值
        [invocation getReturnValue:&returnValue];
    }
    
    return returnValue;
}

//要调用的方法
-(void)textFunctionWithParam9:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 {
    NSLog(@"param1:%@, param2:%@, param3:%ld",param1, param2, param3);
}

十,NSTimer 的@selected传值

#pragma mark -  10,NSTimer 的@selected传值
- (void)test10 {
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    [dict setObject:@"testString" forKey:@"string"];
    [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(onTimer:) userInfo:dict repeats:NO];
}

- (void)onTimer:(NSTimer *)timer {
    NSString *string = [[timer userInfo] objectForKey:@"string"];
    NSLog(@"NSTimer传值:%@",string);
}

十一,UIButton的事件传值

#pragma mark -  11,UIButton 的@selected传值
/*
 思路:
 1,传递的参数,通过button的tag传递
 2,写一个分类,当前方法中,添加事件,不用另起一个方法
 3,直接添加属性
 4, 获取btn所属的控制器,再将控制器要传递的参数暴露出来
 5,自定义button
 */
- (void)test11 {
    UIButton * markButton=[[UIButton alloc] initWithFrame:CGRectMake(280, 0, 30, 30)];
    
    markButton.tag = 18;
    NSString *newProperty = @"newValue";
    objc_setAssociatedObject(markButton, @"newProperty", newProperty, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [markButton addTarget:self action:@selector(addMark:)  forControlEvents:UIControlEventTouchUpInside];
    [markButton setBackgroundColor:[UIColor redColor]];
    [self.view addSubview:markButton];
    

    
}

- (void)addMark:(UIButton *)btn {
    
    NSLog(@"button的tag%ld",(long)btn.tag);
    NSLog(@"button的runtime添加属性%@",objc_getAssociatedObject(btn,@"newProperty"));
    
}

猜你喜欢

转载自blog.csdn.net/a_horse/article/details/83897711
今日推荐