iOS 简单反射机制

提示文章只是用来记录本人自己在学习过程中所遇到的一些问题的解决方案,如果有什么意见可以留言提出来,不喜勿喷哦

占位图

问题提出

问题产生于我所做的第一个项目,项目需要用到 WebView 也就是UIWebView,拦截JS请求的方法还是采用的在 delegate 的回调方法 shouldStartLoadWithRequest 里面拦截 http 请求来实现的。
但是要采用怎么的方式才能井然有序地通过 JS 代用原生方法呢?于是想到了采用反射的机制来实现这种交互。

方法构思

  • 首先得和编写 JS 的人约定好 JS 请求原生方法的 Http 请求格式,例如:以 "cqutobjc://" 这种格式标志来进行方法和参数的提取。
  • 编写一个 JS 调用原生方法的方法列表类,里面包含了所有 JS 要调用的原生方法和具体实现。
  • 编写一个用于拦截 JS 请求的类,UIWebView 的实例化可以不用卸载里面,但是 delegate 必须给这个类。每次 JS 调用原生方法,都在回调方法里面调用反射类进行反射调用。

代码实现

这里我就只展示反射类的代码,其他类的实现可以参照以上描述(被调用的原生方法列表类为Operation类)。

#import <Foundation/Foundation.h>

@interface JudgmentRequest : NSObject

+ (JudgmentRequest *)shareinstance;
-(void)Judgment:(NSArray *)DataArr;

@end
#import "JudgmentRequest.h"
#import "Operation.h"
static Class tmp;

@implementation JudgmentRequest

+ (JudgmentRequest *)shareinstance{
    static JudgmentRequest *tool = nil;
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        tool=[[JudgmentRequest alloc] init];
        tmp = NSClassFromString(@"Operation");
    });
    return tool;
}

- (void)Judgment:(NSArray *)DataArr{
    NSString *methodName = @"";
    
    NSArray *temparr = [DataArr[0] componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"|"]];
    
    if ([temparr count] > 1) {//判断是否有参数
   
    int length = [DataArr count];
    
    if(length >= 1)//有参函数(可以去掉)
    {
    NSMutableArray * paramValueArr = [[NSMutableArray alloc] init];
    for (int i = 0;i < length ; i++) {
        NSArray * dataArray = [DataArr[i] componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"|"]];
        paramValueArr[i] =dataArray[1];
        methodName = [methodName stringByAppendingString:dataArray[0]];
        methodName = [methodName stringByAppendingString:@":"];
    }
    
    SEL sel = NSSelectorFromString(methodName);
    //判断实例中是否包含这个方法,类似的还有是否属于某一个类等接口
    if([tmp respondsToSelector:sel] == YES) {
        
        NSInvocation *inv = [NSInvocation invocationWithMethodSignature:
                             [tmp methodSignatureForSelector:sel]];
        
        [inv setSelector:sel];
        [inv setTarget:tmp];
        
        int paramLength = [paramValueArr count];
        for (int i = 0; i < paramLength; i++) {
            NSString * paramTmp = @"";
            paramTmp = [paramTmp stringByAppendingString:paramValueArr[i]];
            [inv setArgument:&paramTmp  atIndex:i+2];
            [inv retainArguments];
        }
        [inv invoke];
    }
    }
    }
    else//无参函数
    {
        methodName = [methodName stringByAppendingString:DataArr[0]];
        SEL sel = NSSelectorFromString(methodName);
        if([tmp respondsToSelector:sel] == YES) {
            
            NSInvocation *inv = [NSInvocation invocationWithMethodSignature:
                                 [tmp methodSignatureForSelector:sel]];
            
            [inv setSelector:sel];
            [inv setTarget:tmp];
            [inv invoke];
        }
    }
}

注意:具体使用可能需要具体修改!

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,705评论 25 709
  • 用到的组件 1、通过CocoaPods安装 2、第三方类库安装 3、第三方服务 友盟社会化分享组件 友盟用户反馈 ...
    SunnyLeong阅读 14,715评论 1 180
  • 毕业后把宿舍里所有没扔掉的东西都带到了现在住的地方,随意的放着。 有一天整理屋子,他看着我几年里留下的各种东西,告...
    赫赫赤乌阅读 261评论 0 0
  • 采访X那天,我们约好了下午五点在一个露天体育馆见面。领着我们的老师老宁煞有介事地吩咐我们准备好采访大纲,今天的采访...
    彼年_阅读 269评论 0 1
  • 我九十多岁的爷爷,看我太老实本分了,书没读多少,却成了呆子,十分着急,就经常教导我。 爷爷说,人若不敢去吹牛,一点...
    徐克惜愚兄弟阅读 460评论 0 1