【iOS開發】WKWebView與H5交互

最近因為公司的項目要大量用到H5,公司的適配版本也終于提到了iOS8以上,所以是時候換掉陳舊的UIWebView了。用這篇文章來總結一下最近用到的WKWebView相關知識,歡迎各位留言指正交流。

WKWebView的創建

- (WKWebView *)webView {
    if (!_webView) {
        //初始化WKWebViewConfiguration
        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
        /**
         設置代理對象
         ScriptMessageHandler:WKScriptMessageHandler的代理對象
         name:跟后端協調好的響應名稱
        **/
        [config.userContentController addScriptMessageHandler:self name:@"methodName"];

        _webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT - 64) configuration:config];
        
        [_webView  loadRequest:[ NSURLRequest requestWithURL:url]];
        
        _webView.navigationDelegate = self;
    }
    return _webView;
}

在這段代碼中,我們設置了兩個代理,所以應該遵守代理協議,分別是WKNavigationDelegate和WKScriptMessageHandler,兩個代理方法的具體實現會在下文進行說明。這里特別說明WKScriptMessageHandler代理對象的設置并不是使用點語法的形式,而是在初始化webView的時候先初始化WKWebViewConfiguration類型的對象config,然后使用- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration方法設置代理。

WKNavigationDelegate

這個代理我用到的代理方法比較簡單有三個如下,其他的代理方法也有很多文章進行說明,我就不再贅述。

// 頁面開始加載時調用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
}

// 頁面加載完成之后調用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
}

// 頁面加載失敗時調用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation {
}

WKScriptMessageHandler(JS調用原生)

在看這個代理方法之前,我們首先回顧一下webView的創建時調用的一句代碼

 [config.userContentController addScriptMessageHandler:self name:@"methodName"];

在創建config對象時,我們給他綁定一個名為methodName的方法,而這個方法就是和H5同事協定好的用來交互的方法的方法名,里面可以通過傳參來確定接下來進行何種交互,而交互的代碼就寫在代理方法里面,接下來看看代理方法。

- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
          NSString *messageStr = [NSString stringWithFormat:@"%@",message.body];
}

這里的message是js調用methodName方法回傳的信息,我們可以在代理方法中通過解析message得到和H5協定好的特殊標識來進行交互。當然你必須在js的代碼中寫如下代碼才能保證交互成功(PS:這是H5中的JS代碼)。

 window.webkit.messageHandlers. methodName.postMessage()

我個人認為這樣的交互方式其實跟UIWebView通過截取字符串的交互方式有些類似,都是通過和前端協定好的特殊標識符來執行所對應的交互內容,舉個例子,一個H5中有兩個按鈕,點擊第一個按鈕跳轉控制器A,第二個按鈕跳轉控制器B,那H5人員在處理按鈕A和B的交互事件的地方分別寫下如下代碼

 window.webkit.messageHandlers. methodName.postMessage(pushVcA)
 window.webkit.messageHandlers. methodName.postMessage(pushVcB)

我們iOS端在代理方法中寫下如下代碼

- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
          NSString *messageStr = [NSString stringWithFormat:@"%@",message.body];
          if (messageStr isEqualToString:@"pushVcA") {
                 //跳轉控制器A
          }
          if (messageStr isEqualToString:@"pushVcB") {
                //跳轉控制器B
          }
}

這只是一個簡單的交互場景舉例,但是JS調用原生方法就是在這個代理方法中實現。接下來講一下原生如何調用JS方法。

原生調用JS

原生調用JS需要用到WKWebView的方法

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler

我的使用方式為

    NSString *startStr = @"startUploadImgCB('start')";
    [self.webView evaluateJavaScript:startStr completionHandler:^(id _Nullable response, NSError * _Nullable error) {
        NSLog(@"value: %@ error: %@", response, error);
    }];

結合我的使用場景來進行一下說明,我這里的H5需要調用原生相冊和拍照進行圖片上傳,我的代碼是寫在上傳開始前的地方,這里的startUploadImgCB即為JS寫好的方法,start是我傳給JS的參數,目的是告訴JS原生開始上傳圖片,開始上傳動畫。注意這個方法要跟上文中約定好的交互方法methodName方法區分開,methodName是JS調用原生的方法名,而startUploadImgCB是原生調用JS的方法名。
以上就是對本次項目中所用到的原生與H5交互知識的總結,demo需要H5端的配合就不上了,本人才疏學淺,如果有不對的地方煩請各路大神指正,歡迎大家交流!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容