最近在访问私有方法的时候,多于2个参数,因此使用NSInvocation。
一开始,私有方法返回值是int, 如下图:
-(int)xxxx:(int)val vv:(int)vv xx:(int)xx {}
考虑到如果每一种返回值类型都要更新处理,这想想都麻烦。
因此,用NSObject添加分类。
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSObject (Ext)
- (id)textInvocation:(SEL)selector block:(void (^)(NSInvocation *))block;
@end
NS_ASSUME_NONNULL_END
#import "NSObject+Ext.h"
@implementation NSObject (Ext)
- (id)textInvocation:(SEL)selector block:(void (^)(NSInvocation *))block {
    NSMethodSignature *sig = [self methodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
    // 设置参数
    invocation.target = self;
    invocation.selector = selector;
    
    block(invocation);
    
    // 设置返回值
    id result = nil;
    
    // 检查方法返回类型
    const char *returnType = sig.methodReturnType;
    if (strcmp(returnType, @encode(void)) == 0) {
        // 返回类型为 void,无需处理
        [invocation invoke];
    } else if (strcmp(returnType, @encode(id)) == 0) {
        // 返回类型为对象类型
        [invocation invoke];
        [invocation getReturnValue:&result];
    } else if (strcmp(returnType, @encode(NSInteger)) == 0) {
        // 返回类型为 NSInteger
        NSInteger value = 0;
        [invocation invoke];
        [invocation getReturnValue:&value];
        result = @(value); // 封装为 NSNumber
    } else if (strcmp(returnType, @encode(float)) == 0) {
        // 返回类型为 float
        float value = 0.0f;
        [invocation invoke];
        [invocation getReturnValue:&value];
        result = @(value); // 封装为 NSNumber
    } else if (strcmp(returnType, @encode(double)) == 0) {
        // 返回类型为 double
        double value = 0.0;
        [invocation invoke];
        [invocation getReturnValue:&value];
        result = @(value); // 封装为 NSNumber
    } else {
        // 其他基本数据类型,你可以根据需要继续扩展
    }
    
    return result;
}
@end
//调用方法示例
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    NSLog(@"金额:%@",[[Person new] textInvocation:@selector(dataCount:vv:cc:) block:^(NSInvocation * _Nonnull invocation) {
        NSNumber *num = [NSNumber numberWithInt:1];
        NSNumber *num1 = [NSNumber numberWithInt:2];
        NSNumber *num2 = [NSNumber numberWithInt:2];
        [invocation setArgument:&num atIndex:2];
        [invocation setArgument:&num1 atIndex:3];
        [invocation setArgument:&num2 atIndex:4];
    } ]);
}
通过这样的方式, 需要的参数,通过闭包中NSInvocation处理,类型统一在分类中处理。