一.使用UIWebView
方式一:拦截URL原理
- js通过加载url方式被webView拦截,这时候看如果是自己定义的scheme请求就不让webView继续加载请求,否则就继续加载请求。
- webView看加载的请求的host是哪种host进行分别处理。
- 处理oc代码。
- 之后调用stringByEvaluatingJavaScriptFromString调用js代码。
objective-c
js调用OC(js端使用iFrame对url加载 或者 window.location.href = 'haleyAction://getLocation?a=A&b=B')
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSURL *url = request.URL;
NSString *strScheme = url.scheme;
//在该方法中拦截request 处理业务
return YES;
}
OC调用js
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"alert(0)"]];注意:js调用oc属于异步方式oc调用js属于同步方式,且必须在主线程加载,如果js代码比较耗时那么可能会卡顿主线程
方式二:利用JavaScriptCore库
- html直接调用方法:
function locationClick() {getLocation(‘A’,‘B’,‘C’);} - 在oc的delegate回调中实现这个方法,block
objective-c
- (void)webViewDidFinishLoad:(UIWebView *)webView{
JSContext *context = [self valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[@"getLocation"] = ^() {
NSArray *arrArgs = [JSContext currentArguments];
NSString *a = arrArgs[0];
NSString *b = arrArgs[1];
NSString *c = @"C";
NSString *strArgs = [NSString stringWithFormat:@"a=%@,b=%@,c=%@",a,b,c];
[[JSContext currentContext] evaluateScript:[NSString stringWithFormat:@"setLocation('%@')",strArgs]];
};
}- 通过赋值context[@“getLocation”]来实现方法
- 通过
objective-c
NSArray *arrArgs = [JSContext currentArguments];//获取参数JavaScript
js调用OC
function locationClick() {
getLocation(‘A’,‘B’,‘C’);
}
OC调用js(使用JSContext的 evaluateScript方法)
[[JSContext currentContext] evaluateScript:[NSString stringWithFormat:@"setLocation('%@')",strArgs]];注意:js执行时候会进入context的回调,该回调block是在子线程中的。如果刷新ui要切回到主线程
DEMO代码地址 提取码: tj4e
二.使用WKWebView
WKWebView和UIWebView的比较
- wk更节省内存
- wk加载速度刚快
- wk解决了内存泄露问题
- wk刚好适配了ios8+
方式一:拦截URL原理
- js通过加载url方式被webView拦截,这时候看如果是自己定义的scheme请求就不让webView继续加载请求,否则就继续加载请求。
- webView看加载的请求的host是哪种host进行分别处理。
- 处理oc代码。
- 之后调用evaluateJavaScript调用js代码。
objective-c
js调用OC(js客使用iFrame对url加载 或者 window.location.href = 'custumAction://getLocation?a=A&b=B')
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSURL *url = request.URL;
NSString *strScheme = url.scheme;
//在该方法中拦截request 处理业务
return YES;
}
OC调用js
[self.wkWebView evaluateJavaScript:[NSString stringWithFormat:@"setLocation('%@')",strArgs] completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@----%@",result, error);
}];注意:js调用oc属于异步方式oc调用js属于同步方式,且必须在主线程加载,如果js代码比较耗时那么可能会卡顿主线程 WKWebView有个处理js弹窗的代理方法,这个方法必须要实现,如果不实现js的弹窗将会无效
方式二:WKWebView messageHandle方式
- js通过调用方法window.webkit.messageHandlers.getLocation.postMessage({A:‘a’,B:‘b’});其中getLocation为name,{A:‘a’,B:‘b’}相当于参数。
- oc通过 [self.webView.configuration.userContentController addScriptMessageHandler:self name:obj];相当于注册监听。
objective-c
- (void)setCustomHostMessageHandleArr:(NSArray *)customHostMessageHandleArr{
[customHostMessageHandleArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self.configuration.userContentController addScriptMessageHandler:self name:obj];
}];
_customHostMessageHandleArr = customHostMessageHandleArr;
}- js调用时oc会进入回调userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
objective-c
#pragma mark - MessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
//判断是否是需要的值
__block NSString *host = nil;
[self.customHostMessageHandleArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([message.name isEqualToString:obj]) {
host = obj;
*stop = YES;
}
}];
if (host) {
if ([self.messageHandleDelegate respondsToSelector:@selector(BaseWKWebViewMessageHandleDelegate:webView:)]) {
[self.messageHandleDelegate BaseWKWebViewMessageHandleDelegate:message webView:self];
}
}
}- 通过分析message.name来判断是js调用的那个方法,通过分析message.body来获取参数
- 之后调用evaluateJavaScript调用js代码。
JavaScript
js调用OC
window.webkit.messageHandlers.getLocation.postMessage({A:‘a’,B:‘b’});
OC调用js
[self.wkWebView evaluateJavaScript:[NSString stringWithFormat:@"setLocation('%@')",strArgs] completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@----%@",result, error);
}];DEMO代码地址 提取码: tj4e
推荐第三方框架 DSBridge
