最近在访问私有方法的时候,多于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处理,类型统一在分类中处理。