上一篇講了借助 JavaScriptCore 進(jìn)行 OC 與 JS 的交互浊洞,鏈接請(qǐng)戳??
OC 與 JS 交互之 JavaScriptCore
今天總結(jié)一下通過(guò) WKWebView 來(lái)進(jìn)行 OC 與 JS 交互~
WKWebView
WKWebView 是蘋(píng)果爸爸在 iOS8 推出的希望替代 UIWebView 的WebView狮斗,推出了很多新的功能,新的屬性,并且通過(guò) WKScriptMessageHandler惧笛、WKNavigationDelegate仲翎、WKUIDelegate 這三個(gè)協(xié)議,讓請(qǐng)求悯舟、執(zhí)行 web 頁(yè)面的過(guò)程變得更加可控担租。
與之交互用到的三大代理:
WKNavigationDelegate:與頁(yè)面導(dǎo)航加載相關(guān)
WKUIDelegate:與 JS 交互時(shí)的 UI 展示相關(guān),比較 JS 的alert抵怎、confirm奋救、prompt
WKScriptMessageHandler:與 JS 交互相關(guān),通常是 iOS 端注入名稱(chēng)反惕,JS 端通過(guò) window.webkit.messageHandlers.{NAME}.postMessage()來(lái)發(fā)消息到 iOS 端
關(guān)于 WKWebView 的更多細(xì)節(jié)有時(shí)間再總結(jié)下尝艘,今天先說(shuō)說(shuō)有關(guān) OC 與 JS 交互的過(guò)程。
OC 調(diào)用 JS
WKWebViewConfiguration *configuration = [WKWebViewConfiguration new];
configuration.userContentController = [WKUserContentController new];
NSString *sourceStr = @"alert('在載入webview時(shí)通過(guò)oc注入的js方法');";
WKUserScript *script = [[WKUserScript alloc] initWithSource:sourceStr injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
[configuration.userContentController addUserScript:script];
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
_webView.UIDelegate = self;
生成的 configuration 承璃,包含了之后新建 webView 的一系列屬性利耍;再生成一個(gè)腳本片段,包含 JS 的 alert 語(yǔ)句盔粹,將其加給 configuration 的 userContentController隘梨,在開(kāi)始加載 web 頁(yè)面時(shí),注入 JS 方法舷嗡,執(zhí)行這個(gè) JS 語(yǔ)句轴猎。
或者用 webView 的 evaluateJavaScript 直接調(diào)用 JS,與 JavaScriptCore 中的 evaluateScript 類(lèi)似:
NSString *script = @"alert('webview 直接調(diào)用 JS 方法');";
[self.webView evaluateJavaScript:script completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"result: %@, error: %@", result, error);
}];
由于蘋(píng)果爸爸要求用 native 的方式處理 web 中的彈框进萄,這里就需要
controller 實(shí)現(xiàn) UIDelegate 中的方法捻脖,拿到 JS 中的參數(shù),生成彈框中鼠,提醒用戶(hù):
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Tip" message:message preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
}]];
[self presentViewController:alertController animated:YES completion:nil];
}
效果如圖:
UIDelegate 有不同的協(xié)議方法分別對(duì)應(yīng) native 確定蝴簇、選擇等缀、輸入文本框的等彈框时迫,效果還不錯(cuò)~
JS 調(diào)用 OC
先新建一個(gè) html 文件如下:
<!DOCTYPE html>
<html>
<head>
<title>test javascript</title>
<style type="text/css">
* {font-size: 40px;}
</style>
</head>
<body>
<div style="margin-top: 100px">
<input type="button" value="js call oc" onclick="jsCallOC()">
</div>
<script type="text/javascript">
function jsCallOC(){
var message = {
'method' : 'jsCallOC',
'param1' : 'zn',
};
window.webkit.messageHandlers.AppModel.
postMessage({body: message});
}
</script>
</body>
</html>
點(diǎn)擊按鈕,調(diào)用 JS 方法惫搏,在 JS 中
window.webkit.messageHandlers.{NAME}.postMessage() 將 JS 中的對(duì)象轉(zhuǎn)換為 OC 中的處理消息對(duì)象具温,并且將 message 傳遞給他。
//將 self 作為 AppModel 筐赔,處理 JS 傳遞過(guò)來(lái)的數(shù)據(jù)
[configuration.userContentController addScriptMessageHandler:self name:@"AppModel"];
拿到 message 后铣猩,self 需要繼承 WKWebView 的另一個(gè)協(xié)議 WKScriptMessageHandler 的方法,解析消息茴丰,從而實(shí)現(xiàn) JS 到 OC 的調(diào)用:
// MARK: - WKScriptMessageHandler
// 注入 JS 名稱(chēng)达皿,在 JS 端通過(guò) window.webkit.messageHandlers.AppModel.postMessage() 方法來(lái)發(fā)送消息到 native
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
NSLog(@"messageBody: %@", message.body);
NSLog(@"messageName: %@", message.name);
}
參考博客:
WKWebView
WKWebView特性及使用