JavaScript与原生交互

实例样式

原生页面与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(@"哈哈哈");
}];
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351