除了JavaScriptCore,JS调用原生只能异步处理返回值
css
基于URL协议,JS发送请求,在WebView生命周期方法
中拦截到如myURLProtocol://
。 这种方法对于UIWebView和WKWebView通用。java
//WKWebView
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSURL *URL = navigationAction.request.URL;
NSString *scheme = [URL scheme];
if ([scheme isEqualToString:@"myURLProtocol"]) {
[self handleCustomAction:URL]; //本身解析协议
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
//UIWebView
#pragma mark - UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *URL = request.URL;
NSString *scheme = [URL scheme];
if ([scheme isEqualToString:@"myURLProtocol"]) {
[self handleCustomAction:URL]; //本身解析协议
return NO;
}
return YES;
}
复制代码
//WKWebView
[self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@----%@",result, error);
}];
//UIWebView
[_webView stringByEvaluatingJavaScriptFromString:jsStr]; //须要本身另外处理回调
复制代码
iOS下JS与OC互相调用(一)--UIWebView 拦截URL iOS下JS与OC互相调用(二)--WKWebView 拦截URLweb
###1.1.2 基于NSURLProtocol的拦截浏览器
iOS 开发中使用 NSURLProtocol 拦截 HTTP 请求bash
iOS WKWebView (NSURLProtocol)拦截js、css,图片资源app
见第2节异步
见第3节ide
JS的引擎,原生和JS互相访问函数
最先是WebKit中解释执行JS,做用至关于Chrome的V8post
JSContext *context = [[JSContext alloc] init];
// 解析执行 JavaScript 脚本
[context evaluateScript:@"var i = 4 + 8"];
// 转换 i 变量为原生对象
NSNumber *number = [context[@"i"] toNumber];
NSLog(@"var i is %@, number is %@",context[@"i"], number);
复制代码
// 解析执行 JavaScript 脚本
[context evaluateScript:@"function addition(x, y) { return x + y}"];
// 得到 addition 函数
JSValue *addition = context[@"addition"];
// 传入参数执行 addition 函数
JSValue *resultValue = [addition callWithArguments:@[@(4), @(8)]];
// 将 addition 函数执行的结果转成原生 NSNumber 来使用。
NSLog(@"function is %@; reslutValue is %@",addition, [resultValue toNumber]);
复制代码
@protocol YYYJSExports <JSExport>
-(void)record:(NSString *)msg;
@end
@interface YYYUIWebViewJSBridge()<YYYJSExports>
@property (nonatomic, strong) JSContext *jsContext;
@end
@implementation YYYUIWebViewJSBridge
+ (void)registWebView:(UIWebView *_Nonnull)webView withId:(NSString *_Nonnull)webViewId {
if(!webView || !webViewId) return;
SHWUIWebViewJSBridge *bridge = [SHWUIWebViewJSBridge new];
bridge.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
bridge.jsContext[@"shw_analytics"] = bridge;
[bridgeContainer setObject:webView forKey:webViewId];
}
+ (void)deRegistWebViewWithId:(NSString *_Nonnull)webViewId {
if(!webViewId) return;
[bridgeContainer removeObjectForKey:webViewId];
}
- (void)record:(NSString *)msg {
SHWEvent *event = [SHWEvent initEventWithId:_SW_ANALYTICS_EVENTID_WEBVIEW args:@{__SW_KEY_WebView: msg}];
[SHWMsgQueue logEvent:event];
}
复制代码
MessageHandler,做用相似于JSExport,为JS调用原生提供接口。 但原生调用JS,不能像JSContext那样直接调用,而是经过经过evaluateJS。
iOS下JS与OC互相调用(三)--MessageHandler
NSString *jsStr2 = @"window.ctuapp_share_img";
[self.webView evaluateJavaScript:jsStr2 completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@----%@",result, error);
}];
复制代码
//viewWillAppear:
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"ScanAction"];
//viewWillDisappear:
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"ScanAction"];
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
// message.body -- Allowed types are NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull.
NSLog(@"body:%@",message.body);
if ([message.name isEqualToString:@"ScanAction"]) {
NSLog(@"扫一扫");
} else if ([message.name isEqualToString:@"Location"]) {
[self getLocation];
} else if ([message.name isEqualToString:@"Share"]) {
[self shareWithParams:message.body];
}
}
复制代码