iOS WKWebView實現(xiàn)JS與Objective-C交互(一) 附Demo

前言: 根據(jù)需求有時候需要用到JS與Objective-C交互來實現(xiàn)一些功能, 本文介紹實現(xiàn)交互的一種方式, 使用WKWebView的新特性MessageHandler, 來實現(xiàn)JS調(diào)用原生, 原生調(diào)用JS.

一. 基礎(chǔ)說明

WKWebView 初始化時,有一個參數(shù)叫configuration,它是WKWebViewConfiguration類型的參數(shù),而WKWebViewConfiguration有一個屬性叫userContentController,它又是WKUserContentController類型的參數(shù)。WKUserContentController對象有一個方法- addScriptMessageHandler:name:,我把這個功能簡稱為MessageHandler。- addScriptMessageHandler:name:有兩個參數(shù),第一個參數(shù)是userContentController的代理對象,第二個參數(shù)是JS里發(fā)送postMessage的對象。
所以要使用MessageHandler功能,就必須要實現(xiàn)WKScriptMessageHandler協(xié)議。

二. 在JS中使用方法

用法出處
  1. js文件代碼實例
function locationClick() {
                /// "showMessage". 為我們和前端開發(fā)人員的約定
                window.webkit.messageHandlers.showMessage.postMessage(null);
            }

  1. 在ViewController 我們需要做哪些事情

2.1 對WKWebView進行初始化以及設(shè)置

    /// 創(chuàng)建網(wǎng)頁配置對象
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    /// 創(chuàng)建設(shè)置對象
    WKPreferences *preference = [[WKPreferences alloc]init];
    /// 最小字體大小 當將javaScriptEnabled屬性設(shè)置為NO時,可以看到明顯的效果
    preference.minimumFontSize = 40.0;
    /// 設(shè)置是否支持javaScript 默認是支持的
    preference.javaScriptEnabled = YES;
    /// 在iOS上默認為NO,表示是否允許不經(jīng)過用戶交互由javaScript自動打開窗口
    preference.javaScriptCanOpenWindowsAutomatically = YES;
    config.preferences = preference;
    /// 這個類主要用來做native與JavaScript的交互管理
    
    _wkwebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) configuration:config];
    [self.view addSubview:_wkwebView];
    /// Load WebView
#if 0
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://m.benlai.com/huanan/zt/1231cherry"]];
    [self.wkwebView loadRequest:request];
#endif
    
#if 1
    NSString *bundleStr = [[NSBundle mainBundle] pathForResource:@"summerxx-test" ofType:@"html"];
    [self.wkwebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:bundleStr]]];
#endif
    
    // UI代理
    _wkwebView.UIDelegate = self;
    // 導航代理
    _wkwebView.navigationDelegate = self;
    // 是否允許手勢左滑返回上一級, 類似導航控制的左滑返回
    _wkwebView.allowsBackForwardNavigationGestures = YES;
    
    // 添加監(jiān)測網(wǎng)頁加載進度的觀察者
    [self.wkwebView addObserver:self
                     forKeyPath:@"estimatedProgress"
                        options:0
                        context:nil];
    // 添加監(jiān)測網(wǎng)頁標題title的觀察者
    [self.wkwebView addObserver:self
                     forKeyPath:@"title"
                        options:NSKeyValueObservingOptionNew
                        context:nil];

2.2 在合理地方進行注冊

    [self.wkwebView.configuration.userContentController addScriptMessageHandler:self name:@"showMessage"];

2.3 接收JS給我們傳遞消息, 這里我做了一個簡單的彈窗提示

#pragma mark - WKScriptMessageHandler
/// 通過接收JS傳出消息的name進行捕捉的回調(diào)方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    if ([message.name isEqualToString:@"showMessage"]) {
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"title" message:@"messgae" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"同意" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
            NSString *jsStr = [NSString stringWithFormat:@"setLocation('%@')",@"雖然我同意了你, 但是答應我別驕傲."];
            [self.wkwebView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
                NSLog(@"%@----%@",result, error);
            }];
        }];
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            NSLog(@"cancel");
            
        }];
        UIAlertAction *errorAction = [UIAlertAction actionWithTitle:@"拒絕" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
            NSString *jsStr = [NSString stringWithFormat:@"setLocation('%@')",@"雖然我拒絕了你, 但是繼續(xù)愛我好嗎"];
            [self.wkwebView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
                NSLog(@"%@----%@",result, error);
            }];
        }];
        [alertController addAction:errorAction];
        [alertController addAction:okAction];
        [alertController addAction:cancelAction];
        
        // 出現(xiàn)
        [self presentViewController:alertController animated:YES completion:^{
            
        }];
        
    }
}

2.3 銷毀

- (void)dealloc {
    /// Remove removeObserver
    [_wkwebView removeObserver:self
                    forKeyPath:NSStringFromSelector(@selector(estimatedProgress))];
    [_wkwebView removeObserver:self
                    forKeyPath:NSStringFromSelector(@selector(title))];
    WKUserContentController *userCC = self.wkwebView.configuration.userContentController;
    [userCC removeScriptMessageHandlerForName:@"showMessage"];
}

Demo: 演示步驟, 點擊獲取定位 Objective-C獲取到JS消息
點擊拒絕, JS獲取到Objective-C傳遞的消息

如圖:


依舊熱愛生活
依舊熱愛生活

總結(jié): 腦殼疼
備注: 如果遇到跨域問題, 主要還是前端和服務端改一下就好了.

參照 : http://www.itdecent.cn/p/433e59c5a9eb

demo: https://github.com/summerxx27/JS_ObjectiveC_MessageHandler

完~
文/夏天然后

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容