The interaction between OC and JS is summarized in the following figure:

Demo address: github.com/tanghaitao/…

  • The underlying webView is HTTP 2.0 12.0Poor performance
  • The WK base is webKit and the Apple kernel is a little bit more configured,Better performance

1. WebView

Demo address: github.com/tanghaitao/…

Self. webView = [[UIWebView alloc] initWithFrame:self.view.bounds]; self.webView.delegate = self; [self.view addSubview:self.webView]; NSURL *url = [[NSBundle mainBundle] URLForResource:@"index.html" withExtension:nil]; NSURLRequest *reqeust = [NSURLRequest requestWithURL:url]; [self.webView loadRequest:reqeust]; // NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]; // NSString *htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; // [self.webView loadHTMLString:htmlString baseURL:nil];Copy the code

Order of execution:

ShouldStartLoadWithRequest/whether/control load * * * * * * * * * * * * * * * * gorgeous line * * * * * * * * * * * * * * * * start loading!!!!!!!!!! / / webViewDidStartLoad * * * * * * * * * * * * * * * * gorgeous line * * * * * * * * * * * * * * * * load finished!!!!!!!!!! // webViewDidFinishLoadCopy the code
// Start loading - (void)webViewDidStartLoad (UIWebView *)webView{// Start loading - (void)webViewDidStartLoad (UIWebView *)Copy the code
// load done - (void)webViewDidFinishLoad:(UIWebView *)webView{NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"]; Self. title = title; self.title = title; }Copy the code
/ / load all the request data, and control is loaded - (BOOL) webView: (UIWebView *) webView shouldStartLoadWithRequest (NSURLRequest *) request NavigationType :(UIWebViewNavigationType)navigationType{//navigationType JS response style click, submit, return, refresh, repeat submit, // Request: host + route: return NO; // Intercept, do not execute the request}Copy the code

1.2 OC – > JS

- (IBAction)didClickRightItemClick:(id)sender {NSLog(@" response button "); // OC --> JS NSLog(@"%@",[self.webView stringByEvaluatingJavaScriptFromString:@"showAlert('mumu')"]); }Copy the code

index.html

<script> function showAlert(name){alert(' I am popover '+ name); } </script>Copy the code

JS – > 1.2 OC

Click on the HTML page in the emulator button click jump effect of OC method < a href = “tzedu: / / getSum: / helloword/js” > click jump effect OC method < / a >

Is called shouldStartLoadWithRequest

/ / load all the request data, and control is loaded - (BOOL) webView: (UIWebView *) webView shouldStartLoadWithRequest (NSURLRequest *) request navigationType:(UIWebViewNavigationType)navigationType{ }Copy the code
po request
<NSMutableURLRequest: 0x600003a80ad0> { URL: tzedu://getSum/helloword/js }
Copy the code

Three important properties of NSURL

    NSString *urlStr = @"https://www.baidu.com/photos";
    NSURL *url2 = [NSURL URLWithString:urlStr];
    NSLog(@"scheme :%@, host :%@, relativePath :%@",url2.scheme,url2.host,url2.relativePath);
Copy the code

Scheme: HTTPS, host :www.baidu.com, relativePath :/photos

    // http://www.example.com/index.html -> http
    // tzedu://getPlus/helloword/js -> tzedu
Copy the code

2. JavaScriptCoreDemo

JS – > 2.1 OC

Demo address: github.com/tanghaitao/…

#import <JavaScriptCore/JavaScriptCore.h> @property (nonatomic, strong) JSContext *jsContext; - (void)webViewDidFinishLoad:(UIWebView *)webView{ NSString *titlt = [webView stringByEvaluatingJavaScriptFromString:@"document.title"]; self.title = titlt; JSContext * JSContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; self.jsContext = jsContext; [jsContext evaluateScript:@"var arr = ['NSLog',' Falcondragon ',' yeaku ']"]; // Click the popup button... Js -> oc jsContext[@"showMessage"] = ^{NSArray *arr = [jsContext currentArguments]; NSLog(@"=====%@",arr); }; }Copy the code

2.2 OC – > JS

- (IBAction)didClickRightItemAction:(id)sender {NSLog(@" response "); [self.jsContext evaluateScript:@"submit()"]; }Copy the code

index.html

<script> function showAlert(){showMessage("... +arr); } function submit(){ alert('submit'); } function ocCalljs(dict){ var name = dict['name']; var age = dict['age']; alert(name + age); // return showDict(dict)} </script>Copy the code

alert(‘submit’);

For more information, see Demo.

3. WKWebView

Demo address: github.com/tanghaitao/…

WKWebView is mainly to pay attention to the problem of cross-domain Cookie failure, the solution is to add new data on the original Cookie, the specific code of their own online search

Request is initialized using WKWebViewConfiguration:

#import <WebKit/WebKit.h> @interface WKMessageHandleVC ()<WKUIDelegate,WKScriptMessageHandler> @property (strong, nonatomic) WKWebView *webView; @end - (void)viewDidLoad { [super viewDidLoad]; WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);" ; WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; WKUserContentController *wkUController = [[WKUserContentController alloc] init]; [wkUController addUserScript:wkUScript]; / / ratio, size to adapt to the equipment size config. UserContentController = wkUController; self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; self.webView.navigationDelegate = self; self.webView.UIDelegate = self; [self.view addSubview:self.webView]; NSURL *url = [[NSBundle mainBundle] URLForResource:@"index.html" withExtension:nil]; [self.webView loadFileURL:url allowingReadAccessToURL:url]; }Copy the code

Set the title:

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    self.title = webView.title;
}
Copy the code

Because the js popup interface is not very nice, it is recommended to use oc popup:

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler { UIAlertController *alert = [UIAlertController alertControllerWithTitle: @ "alert" message: the message preferredStyle: UIAlertControllerStyleAlert]; [alert addAction: [UIAlertAction actionWithTitle: @ "know" style: UIAlertActionStyleCancel handler: ^ (UIAlertAction * _Nonnull  action) { completionHandler(); }]]; [self presentViewController:alert animated:YES completion:nil]; }Copy the code

3.1 OC –> JS

 NSString *jsStr2 = @"var arr = [3, 'haitao', 'abc']; ";
    // oc -> js
    [self.webView evaluateJavaScript:jsStr2 completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        NSLog(@"%@----%@",result, error);
    }];
Copy the code

3.2 JS –> OC

3.2.1 Request Interception (Unconventional)

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction DecisionHandler :(void (^)(WKNavigationActionPolicy))decisionHandler {// intercepting -- hyperlink -- custom // if (route) {// // NSLog(@"%@",navigationAction.request); // // decisionHandler(WKNavigationActionPolicyCancel); // // } decisionHandler(WKNavigationActionPolicyAllow); }Copy the code

3.2.2 Do not Intercept Requests (General Processing Method)

Normally wkWebView handles the event handle, in the class WkMessageHandlevc. m, index.html

<script> function loadURL(url) { var iFrame; iFrame = document.createElement("iframe"); iFrame.setAttribute("src", url); iFrame.setAttribute("style", "display:none;" ); iFrame.setAttribute("height", "0px"); iFrame.setAttribute("width", "0px"); iFrame.setAttribute("frameborder", "0"); document.body.appendChild(iFrame); iFrame.parentNode.removeChild(iFrame); iFrame = null; } function showAlert(messgae){alert(' I am a lovely box \n +messgae+'\n'+arr[1]); return "token"; } function submit(){alert('<<<< >>>>>'); loadURL("tzedu://jsCallOC? username=Cooci&password=123456"); } function messgaeHandle () {/ / JS - > OC / / ANDROID window. Its. MessageHandlers. MessgaeOC. PostMessage (" haitao "); } </script>Copy the code

JS file JS –> OC key code:

Function messgaeHandle () {/ / JS - > OC / / ANDROID window. Its. MessageHandlers. MessgaeOC. PostMessage (" haitao "); }Copy the code

Window. Its. MessageHandlers. MessgaeOC. PostMessage messageHandlers its kernel processing class, MessgaeOC corresponds to the name in viewWillAppear :@”messgaeOC”

  • Click the “Message” button in the HTML page to report an error

      -[WKMessageHandleVC userContentController:didReceiveScriptMessage:]: unrecognized selector sent to instance 0x7fe02740aa60
    Copy the code

Need to perform in the oc agent function [WKMessageHandleVC userContentController: didReceiveScriptMessage:]

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"%@---%@",message.name,message.body); // if (message.name) {// <#statements#> //}}Copy the code
- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"messgaeOC"];
}

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"messgaeOC"];
}
Copy the code

The above needs occur in pairs and will result in circular references if disappear is not called.

4. WebViewJavascriptBridge

Demo address: github.com/tanghaitao/…

  • Transitioning directly from UIWebView to WkWebView, the processing logic (intercepting requests, non-intercepting proxy functions) does not need to be modified
  • Pod 'WebViewJavascriptBridge', '~ > 6.0.3'
+ (instancetype)bridge:(id)webView {
#if defined supportsWKWebView
    if ([webView isKindOfClass:[WKWebView class]]) {
        return (WebViewJavascriptBridge*) [WKWebViewJavascriptBridge bridgeForWebView:webView];
    }
#endif
        //#define WVJB_WEBVIEW_TYPE UIWebView
    if ([webView isKindOfClass:[WVJB_WEBVIEW_TYPE class]]) {
        WebViewJavascriptBridge* bridge = [[self alloc] init];
        [bridge _platformSpecificSetup:webView];
        return bridge;
    }
    [NSException raise:@"BadWebViewType" format:@"Unknown web view type."];
    return nil;
}

Copy the code

JS – > 4.1 OC

#import "ViewController.h"
#import <WebViewJavascriptBridge.h>
#import <WebKit/WebKit.h>

// An iOS/OSX bridge for sending messages between Obj-C and JavaScript in WKWebViews, UIWebViews & WebViews.
@interface ViewController ()<WKUIDelegate,WKNavigationDelegate>
@property (strong, nonatomic) WKWebView   *webView;
@property (nonatomic, strong) WebViewJavascriptBridge *wjb;
@end

// JS-->OC
    self.wjb = [WebViewJavascriptBridge  bridgeForWebView:self.webView];
    [self.wjb setWebViewDelegate:self];
    [self.wjb  registerHandler:@"jsCallsOC" handler:^(id data, WVJBResponseCallback responseCallback) {
       
        NSLog(@"%@---%@----%@",[NSThread currentThread],data,responseCallback);
    }];

Copy the code

The index.html file:

<script> function setupWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; document.documentElement.appendChild(WVJBIframe); setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, {0} setupWebViewJavascriptBridge (function (bridge) / / JS OCCallJSFunction define the identity of the called method Bridge. RegisterHandler ('OCCallJSFunction', function(data, responseCallback) {alert('JS method called :'+data); ResponseCallback ('js executed '); }) }) function showWBJ(){ WebViewJavascriptBridge.callHandler('jsCallsOC', {'haitao': '18'}, function(response) { alert(response); }) } </script>Copy the code

. Click on the button ‘submit’, WebViewJavascriptBridge callHandler (‘ jsCallsOC ‘{‘ haitao’ : ’18’}, funx x x, will response oc jsCallsOC registered in processing the request

4.2 OC –> JS

Copy the code
ResponseCallback :^(id responseData) {NSLog(@"%@--%@",[NSThread]) currentThread],responseData); }];Copy the code

For more processing, such as WKNavigationDelegate, see Demo

5. WebViewJavascriptBridgeUIWebView

Learn by yourself, refer to Demo for specific usage

6. CordovaWebView

Learn by yourself, refer to Demo for specific usage