JavaScript与原生交互

2019-03-29  本文已影响0人  今晚月色
实例样式

原生页面与HTML页面进行相互调用

方式 适用对象
拦截URL UIWebViewWKWebView
JavaScriptCore UIWebView
MessageHandler WKWebView
WebViewJavascriptBridge UIWebViewWKWebView

实例HTML代码

    <body>
        <h2>按钮点击</h2>
        <button type="submit" onclick="buttonEvent()" id="submitButto">提交</button>
        <h2>文件上传</h2>
        <input type="file" />
        <h2>原生注入数据</h2>
        <input type="text" id="textField">
        <input type="button" onclick="getTextEvent()" value="开始注入">
        <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 buttonEvent(){
                loadURL("/buttonEvent");
                buttonDidPapped();
            }
        
            function getTextEvent() {
                loadURL("/getText");
                getTextButtonDidPapped();
            }
            function getText(text){
                document.getElementById("textField").value = text;
            }
        </script>
    </body>       

拦截URL

UIWebView

遵循UIWebViewDelegate调用- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType方法,判断获取的Url地址

// 调用JS
if ([request.URL.absoluteString hasSuffix:@"buttonEvent"]) {
    UIAlertController *vc = [UIAlertControlleralertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
        [vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
    }]];
    [self presentViewController:vc animated:true completion:nil];  
    return NO;
} 
// 注入数据给JS
if ([request.URL.absoluteString hasSuffix:@"getText"]) { 
    [webView stringByEvaluatingJavaScriptFromString:@"getText('哈哈')"];
     return NO;
}
return YES;

WKWebView

遵循WKNavigationDelegate调用- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler方法判断获取的地址

NSString *strRequest = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
// 调用JS
if ([strRequest hasSuffix:@"buttonEvent"]) {
    UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
    [vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
    }]];
    [self presentViewController:vc animated:true completion:nil];
    decisionHandler(WKNavigationActionPolicyCancel);
} else if ([strRequest hasSuffix:@"getText"]) { // 注入数据给JS
    [webView evaluateJavaScript:@"getText('哈哈')" completionHandler:^(id _Nullable info, NSError * _Nullable error) {
        NSLog(@"Error--%@, info--%@", error, info);
    }];
    decisionHandler(WKNavigationActionPolicyCancel);
} else {
    decisionHandler(WKNavigationActionPolicyAllow);
}

JavaScriptCore

  1. 导入<JavaScriptCore/JavaScriptCore.h>
  2. 遵循<UIWebViewDelegate>并实现- (void)webViewDidFinishLoad:(UIWebView *)webView方法。
// 对JSContext对象进行初始化
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 验证JSContext对象是否初始化成功
context.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue){
    context.exception = exceptionValue;
};
 
// 调用JS  
context[@"buttonDidPapped"] = ^{
    UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
    [vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
    }]];
    [self presentViewController:vc animated:true completion:nil];
};
 
// 注入数据给JS   
context[@"getTextButtonDidPapped"] = ^{
    dispatch_async(dispatch_get_main_queue(), ^{
      [self.webView stringByEvaluatingJavaScriptFromString:@"getText('哈哈')"];
        });
};

MessageHandler

  1. 修改js中的方法, 通过window.webkit.messageHandlers+操作方法
function buttonEvent(){
    window.webkit.messageHandlers.buttonEvent.postMessage(null);
}
        
function getTextEvent() {
    window.webkit.messageHandlers.getTextEvent.postMessage(null);
}
  1. 遵循WKScriptMessageHandler
  2. - (void)viewWillAppear:(BOOL)animated中添加scriptMessageHandler
  3. - (void)viewWillDisappear:(BOOL)animated中移除scriptMessageHandler
  4. 实现WKScriptMessageHandler方法
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"buttonEvent"];
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"getTextEvent"];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"buttonEvent"];
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"getTextEvent"];
}

#pragma mark - WKScriptMessageHandler Method
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    // 调用JS
    if ([message.name isEqualToString:@"buttonEvent"]) {
        UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
        [vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        [self presentViewController:vc animated:true completion:nil];
        return;
    }
    
    // 注入数据给JS
    if  ([message.name isEqualToString:@"getTextEvent"]) {
        [self.webView evaluateJavaScript:@"getText('哈哈')" completionHandler:^(id _Nullable info, NSError * _Nullable error) {
            NSLog(@"Error--%@, info--%@", error, info);
        }];
        return;
    }
}

WebViewJavascriptBridge

HTML代码

<body>
    <h2>按钮点击</h2>
    <input id = 'submitBtn' type="button" value="提交按钮" onclick="submitClick()"/>
    <h2>文件选择</h2>
    <input type="file" id="image">
    <h2>注入数据</h2>
    <input type="text" id="getTextField" />
    <input type="button" value="开始获取" id = 'startGet' onclick="getTextClick()"/>
    <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 = 'https://__bridge_loaded__';
            document.documentElement.appendChild(WVJBIframe);
            setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
        }

        setupWebViewJavascriptBridge(function(bridge) {

        })

        function submitClick() {
            WebViewJavascriptBridge.callHandler('submitClick', null, function(response) {
                
            });
        }
        function getTextClick() {
            WebViewJavascriptBridge.callHandler('getTextClick', null, function(response) {
                document.getElementById("getTextField").value = response;
            });
        }
    </script>
</body>

第三方库:地址

  1. 添加WebViewJavascriptBridge
  2. 导入头文件#import <WebViewJavascriptBridge.h>
  3. 声明方法@property WebViewJavascriptBridge* bridge;
  4. 与WebView关联
_bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];

[_bridge setWebViewDelegate:self];
  1. 调用js
[_bridge registerHandler:@"submitClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
        [vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        [self presentViewController:vc animated:true completion:nil];
}];
  1. 注入数据
[_bridge registerHandler:@"getTextClick" handler:^(id data, WVJBResponseCallback responseCallback) {
        responseCallback(@"哈哈哈");
}];
上一篇下一篇

猜你喜欢

热点阅读