之前公司提出这样的需求,就是把原生的网络请求转换到用js来请求,打包成sdk,然而这样的需求在我看来,我不懂为什么,,。。当然,这是他们的问题。和我们好像没什么太大的关系,算了这些都是白说,主要的就是要改需求,然后再打包成sdk;
直接代码解释吧。。。。。
代码中的核心问题就是创建一个网络请求类,
首先创建一个网络请求类,
@interface msdk ()<UIWebViewDelegate>
//加载web页面的,主要的目的是要加载那些请求的js代码进来
@property (nonatomic , strong) UIWebView *webView;
//处理js用到的
@property (nonatomic , strong) JSContext *jsContext;
//加载url
@property (nonatomic , strong) NSString *urlPath;
//判断url是加载本地的还是加载网络上的
@property (nonatomic , assign) BOOL isLocal;
@end
首先我们要把这个类定义为一个单例:
static msdk *_instance;
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
if (_instance == nil) {
_instance = [super allocWithZone:zone];
_instance.webView = [[UIWebView alloc]initWithFrame:CGRectZero];
_instance.webView.delegate = _instance;
}
});
return _instance;
}
+(instancetype)ShareInstance{
//return _instance;
return [[self alloc]init];
}
-(id)copyWithZone:(NSZone *)zone
{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
当然肯定是要设置代理的,这样的话就可以在加载完web页面之后就可以获取该webView的js上下文了
-(void)webViewDidFinishLoad:(UIWebView *)webView{
//获取该UIWebview的javascript上下文
self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
if (_isLocal && self.srv) {
[self msdk_setSer:self.srv];
}
}
加载本地web(当然你肯定是要设置请求地址的ip)
-(void)msdk_loadLocalWEB:(NSString *)urlPath{
self.isLocal = YES;
self.urlPath = urlPath;
NSString * htmlPath = [[NSBundle mainBundle] pathForResource:urlPath
ofType:nil];
NSURL *url = [NSURL URLWithString:htmlPath];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
加载网络web
-(void)msdk_loadNetworkWEB:(NSString *)urlPath{
self.isLocal = NO;
self.urlPath = urlPath;
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlPath]]];
}
前方高能,最主要的是地方
- (void)msdk_ctr:(NSMutableDictionary*)paramter success:(void (^) (NSDictionary* result))success failure:(void (^)(NSString *error))failure;{
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
//标明是ios的请求
paramter[@"platform"] = @"ios";
// 请求的接口是哪一个
dic[@"type"] = paramter[@"func"];
dic[@"data"] = paramter;
NSString *type = dic[@"type"];
//添加一个方法名为type的js方法
[self.jsContext evaluateScript:[NSString stringWithFormat:@"function %@(a){}",type]];
//把js方法替换成oc原生的方法,当调用type的js方法,就会转化为调用下面block里面的方法,下面的value就是调用的参数
self.jsContext[type] = ^(JSValue *value){
NSDictionary *dic = [value toObject];
if (success &&[dic[@"result"] isEqualToString:@""]){
dispatch_async(dispatch_get_main_queue(), ^{
success(dic);
});
}
else if (failure && ![dic[@"result"] isEqualToString:@""]){
dispatch_async(dispatch_get_main_queue(), ^{
failure(dic[@"result"]);
});
}
};
NSData * paramter_data = [NSJSONSerialization dataWithJSONObject:dic options:0 error:nil];
NSString * js_paramter = [[NSString alloc] initWithData:paramter_data encoding:NSUTF8StringEncoding];
//调用js请求方法
[self.jsContext evaluateScript:[NSString stringWithFormat:@"msdk_ctrl('%@');",js_paramter]];
}
好了,大概就是这样了
使用的时候再介绍一下吧
//需要在AppDelegate 里面设置,
msdk *msdk_agent = [msdk ShareInstance];
//这是加载本地的
[_msdk_agent msdk_loadLocalWEB:@"web/mobile.debug.htm"];
//data是一个字典
[self.msdk_agent msdk_ctr:data success:^(NSDictionary *result) {
//请求成功
} failure:^(NSString *error) {
//请求失败
}];
不好意思,项目还没拆分,,所以就没上传代码,,过段时间上传代码。。。