NSInvocation封装

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容