Skip to content

一.使用UIWebView

方式一:拦截URL原理

  1. js通过加载url方式被webView拦截,这时候看如果是自己定义的scheme请求就不让webView继续加载请求,否则就继续加载请求。
  2. webView看加载的请求的host是哪种host进行分别处理。
  3. 处理oc代码。
  4. 之后调用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库

  1. html直接调用方法:function locationClick() {getLocation(‘A’,‘B’,‘C’);}
  2. 在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]];
		    };
}
  1. 通过赋值context[@“getLocation”]来实现方法
  2. 通过
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原理

  1. js通过加载url方式被webView拦截,这时候看如果是自己定义的scheme请求就不让webView继续加载请求,否则就继续加载请求。
  2. webView看加载的请求的host是哪种host进行分别处理。
  3. 处理oc代码。
  4. 之后调用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方式

  1. js通过调用方法window.webkit.messageHandlers.getLocation.postMessage({A:‘a’,B:‘b’});其中getLocation为name,{A:‘a’,B:‘b’}相当于参数。
  2. 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;
}
  1. 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];
        }
    }
}
  1. 通过分析message.name来判断是js调用的那个方法,通过分析message.body来获取参数
  2. 之后调用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

世界很美 而你正好有空