除了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];
}
}
複製代碼