WKWebView 與 JS 交互的特有方法

WKWebView 在與 JS 的交互時特有的方法:

WKUIDelegate 方法
MessageHandler 方法

  1. WKUIDelegate 方法

WKUIDelegate 協(xié)議包含一些函數(shù)用來監(jiān)聽 web JS 想要顯示 alert 或 confirm 時觸發(fā)。我們?nèi)绻?WKWebView 中加載一個 web 并且想要 web JS 的 alert 或 confirm 正常彈出,就需要實現(xiàn)對應(yīng)的代理方法。( 如果沒有實現(xiàn)對應(yīng)的代理方法,則 webview 將會按照默認操作去做出行為。)

下面是在 WKUIDelegate 監(jiān)聽 web 要顯示 alert 的代理方法中用 Native UIAlertController 替代 JS 中的 alert 顯示的例子 :

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    // 用 Native 的 UIAlertController 彈窗顯示 JS 將要提示的信息
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒"     message:message preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"知道了"     style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        // 函數(shù)內(nèi)必須調(diào)用 completionHandler
        completionHandler();
    }]];

    [self presentViewController:alert animated:YES completion:nil];
}
  1. MessageHandler 方法

MessageHandler 是繼 Native 截獲 JS 假請求后另一種 JS 調(diào)用 Native 的方法,該方法利用了 WKWebView 的新特性實現(xiàn)。對比截獲假 Request 的方法來說,MessageHandler 傳參數(shù)相對簡單方便。

MessageHandler 指什么?

WKUserContentController 類有一個方法:

- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;

該方法用來添加一個腳本處理器,可以在處理器內(nèi)對 JS 腳本調(diào)用的方法做出處理,從而達到 JS 調(diào)用 Native 的目的。

那么 WKUserContentController 類和 WKWebView 有什么關(guān)系呢?

在 WKWebView 的初始化函數(shù)中有一個入?yún)?configuration,它的類型是 WKWebViewConfiguration。WKWebViewConfiguration 中包含一個屬性 userContentController,這個 userContentController 就是 WKUserContentController 類型的實例,我們可以用這個 userContentController 來添加不同名稱的腳本處理器。

2.1. MessageHandler 的坑

回到 - (void)addScriptMessageHandler:name: 方法上面,該方法添加一個腳本消息處理器(第一個入?yún)?scriptMessageHandler),并且給這個處理器起一個名字(第二個入?yún)?name)。不過這個函數(shù)在使用的時候有個坑:scriptMessageHandler 入?yún)粡娨?,那么如果你把當?WKWebView 所在的 UIViewController 作為第一個入?yún)?,這個 viewController 被他自己所持有的 webview.configuration. userContentController 所持有,就會造成循環(huán)引用。

640.jpg

我們可以通過 - (void)removeScriptMessageHandlerForName: 方法刪掉 userContentController 對 viewController 的強引用。所以一般情況下我們的代碼會在 viewWillAppear 和 viewWillDisappear 成對兒的添加和刪除 MessageHandler:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.webview.configuration.userContentController addScriptMessageHandler:self name:@"YourFuncName"];
}

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

WKScriptMessageHandler 協(xié)議

WKScriptMessageHandler 是腳本信息處理器協(xié)議,如果想讓一個對象具有腳本信息處理能力就必須使其遵循該協(xié)議。

WKScriptMessageHandler 協(xié)議內(nèi)部非常簡單,只有一個方法,我們必須要實現(xiàn)該方法(@required):

// WKScriptMessageHandler 協(xié)議方法,在接收到腳本信息時觸發(fā)
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    // message 有兩個屬性:name 和 body
    // message.name 可以用于區(qū)別要做的處理
    if ([message.name isEqualToString:@"YourFuncName"]) {
        // message.body 相當于 JS 傳遞過來的參數(shù)
        NSLog(@"JS call native success %@", message.body);
    }
}

補充 JS 的代碼:

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

相關(guān)閱讀更多精彩內(nèi)容

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