提示:文章只是用來記錄本人自己在學(xué)習(xí)過程中所遇到的一些問題的解決方案,如果有什么意見可以留言提出來,不喜勿噴哦!

占位圖
問題提出
問題產(chǎn)生于我所做的第一個(gè)項(xiàng)目,項(xiàng)目需要用到 WebView 也就是UIWebView,攔截JS請(qǐng)求的方法還是采用的在 delegate 的回調(diào)方法 shouldStartLoadWithRequest 里面攔截 http 請(qǐng)求來實(shí)現(xiàn)的。
但是要采用怎么的方式才能井然有序地通過 JS 代用原生方法呢?于是想到了采用反射的機(jī)制來實(shí)現(xiàn)這種交互。
方法構(gòu)思
- 首先得和編寫 JS 的人約定好 JS 請(qǐng)求原生方法的 Http 請(qǐng)求格式,例如:以 "cqutobjc://" 這種格式標(biāo)志來進(jìn)行方法和參數(shù)的提取。
- 編寫一個(gè) JS 調(diào)用原生方法的方法列表類,里面包含了所有 JS 要調(diào)用的原生方法和具體實(shí)現(xiàn)。
- 編寫一個(gè)用于攔截 JS 請(qǐng)求的類,UIWebView 的實(shí)例化可以不用卸載里面,但是 delegate 必須給這個(gè)類。每次 JS 調(diào)用原生方法,都在回調(diào)方法里面調(diào)用反射類進(jìn)行反射調(diào)用。
代碼實(shí)現(xiàn)
這里我就只展示反射類的代碼,其他類的實(shí)現(xiàn)可以參照以上描述(被調(diào)用的原生方法列表類為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) {//判斷是否有參數(shù)
int length = [DataArr count];
if(length >= 1)//有參函數(shù)(可以去掉)
{
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);
//判斷實(shí)例中是否包含這個(gè)方法,類似的還有是否屬于某一個(gè)類等接口
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:¶mTmp atIndex:i+2];
[inv retainArguments];
}
[inv invoke];
}
}
}
else//無參函數(shù)
{
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];
}
}
}
注意:具體使用可能需要具體修改!