使用WKWebView的時候误褪,如果想要實現(xiàn)JS調(diào)用OC方法憔儿,除了攔截URL之外医清,還有一種簡單的方式。那就是利用WKWebView的新特性MessageHandler來實現(xiàn)JS調(diào)用原生方法铺罢。
MessageHandler 是什么艇挨?
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é)議司忱。?
我們在該API的描述里可以看到在JS中的使用方法:
window.webkit.messageHandlers..postMessage()//其中,就是上面方法里的第二個參數(shù)`name`碉怔。//例如我們調(diào)用API的時候第二個參數(shù)填@"Share"烘贴,那么在JS里就是://window.webkit.messageHandlers.Share.postMessage()//是一個鍵值對,鍵是body撮胧,值可以有多種類型的參數(shù)桨踪。// 在`WKScriptMessageHandler`協(xié)議中,我們可以看到mssage是`WKScriptMessage`類型芹啥,有一個屬性叫body锻离。// 而注釋里寫明了body 的類型:Allowed types are NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull.
怎么使用MessageHandler?
1.創(chuàng)建WKWebViewConfiguration對象墓怀,配置各個API對應的MessageHandler汽纠。
WKUserContentController對象可以添加多個scriptMessageHandler。
看了示例代碼傀履,會很容易理解虱朵。示例代碼如下:
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
? ? configuration.userContentController = [WKUserContentController new];
? ? [configuration.userContentController addScriptMessageHandler:self name:@"ScanAction"];
? ? [configuration.userContentController addScriptMessageHandler:self name:@"Location"];
? ? [configuration.userContentController addScriptMessageHandler:self name:@"Share"];
? ? [configuration.userContentController addScriptMessageHandler:self name:@"Color"];
? ? [configuration.userContentController addScriptMessageHandler:self name:@"Pay"];
? ? [configuration.userContentController addScriptMessageHandler:self name:@"Shake"];
? ? [configuration.userContentController addScriptMessageHandler:self name:@"GoBack"];
? ? [configuration.userContentController addScriptMessageHandler:self name:@"PlaySound"];
? ? WKPreferences *preferences = [WKPreferences new];
? ? preferences.javaScriptCanOpenWindowsAutomatically = YES;
? ? preferences.minimumFontSize = 40.0;
? ? configuration.preferences = preferences;
2.創(chuàng)建WKWebView。
這里沒什么好說的,直接看示例代碼吧:
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
? ? NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil];
? ? NSURL *fileURL = [NSURL fileURLWithPath:urlStr];
? ? [self.webView loadFileURL:fileURL allowingReadAccessToURL:fileURL];
? ? self.webView.navigationDelegate = self;
? ? self.webView.UIDelegate = self;
? ? [self.view addSubview:self.webView];
3.實現(xiàn)協(xié)議方法碴犬。
我這里實現(xiàn)了兩個協(xié)議絮宁,WKUIDelegate是因為我在JS中彈出了alert 。WKScriptMessageHandler是因為我們要處理JS調(diào)用OC方法的請求服协。?
先看實現(xiàn)協(xié)議方法的示例代碼:
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
//? ? message.body? --? Allowed types are NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull.
? ? if ([message.name isEqualToString:@"ScanAction"]) {
? ? ? ? NSLog(@"掃一掃");
? ? } else if ([message.name isEqualToString:@"Location"]) {
? ? ? ? [self getLocation];
? ? } else if ([message.name isEqualToString:@"Share"]) {
? ? ? ? [self shareWithParams:message.body];
? ? } else if ([message.name isEqualToString:@"Color"]) {
? ? ? ? [self changeBGColor:message.body];
? ? } else if ([message.name isEqualToString:@"Pay"]) {
? ? ? ? [self payWithParams:message.body];
? ? } else if ([message.name isEqualToString:@"Shake"]) {
? ? ? ? [self shakeAction];
? ? } else if ([message.name isEqualToString:@"GoBack"]) {
? ? ? ? [self goBack];
? ? } else if ([message.name isEqualToString:@"PlaySound"]) {
? ? ? ? [self playSound:message.body];
? ? }
}
WKScriptMessage有兩個關鍵屬性name?和?body绍昂。?
因為我們給每一個OC 方法取了一個name,那么我們就可以根據(jù)name 來區(qū)分執(zhí)行不同的方法偿荷。body 中存著JS 要給OC 傳的參數(shù)窘游。?
關于參數(shù)body 的解析,我就舉一個body中放字典的例子跳纳,其他的稍后可以看demo忍饰。?
解析JS 調(diào)用OC 實現(xiàn)分享的參數(shù):
- (void)shareWithParams:(NSDictionary *)tempDic
{
? ? if (![tempDic isKindOfClass:[NSDictionary class]]) {
? ? ? ? return;
? ? }
? ? NSString *title = [tempDic objectForKey:@"title"];
? ? NSString *content = [tempDic objectForKey:@"content"];
? ? NSString *url = [tempDic objectForKey:@"url"];
? ? // 在這里執(zhí)行分享的操作? ? // 將分享結果返回給js? ? NSString *jsStr = [NSString stringWithFormat:@"shareResult('%@','%@','%@')",title,content,url];
? ? [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
? ? ? ? NSLog(@"%@----%@",result, error);
? ? }];
}
message.boby 就是JS 里傳過來的參數(shù)。我們不同的方法先做一下容錯性判斷寺庄。然后正常取值就可以了喘批。
4.處理HTML中JS調(diào)用。
HMTL的源碼跟之前的HTML內(nèi)容差不多铣揉,只有JS的調(diào)用部分改變了饶深。
// 傳nullfunctionscanClick(){ window.webkit.messageHandlers.ScanAction.postMessage(null);
}// 傳字典? ? ? ? ? ? ? functionshareClick(){? ? window.webkit.messageHandlers.Share.postMessage({title:'測試分享的標題',content:'測試分享的內(nèi)容',url:'http://www.baidu.com'});
}// 傳字符串functionplaySound(){
? ? window.webkit.messageHandlers.PlaySound.postMessage('shake_sound_male.wav');
}// 傳數(shù)組functioncolorClick(){? ? window.webkit.messageHandlers.Color.postMessage([67,205,128,0.5]);
}
5.OC調(diào)用JS
這里使用WKWebView 實現(xiàn)OC 調(diào)用JS方法跟上一篇是一樣的,還是利用?
- evaluateJavaScript:completionHandler:逛拱。像下面這樣使用:
// 將分享結果返回給js NSString *jsStr = [NSString stringWithFormat:@"shareResult('%@','%@','%@')",title,content,url];
? ? [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
? ? ? ? NSLog(@"%@----%@",result, error);
? ? }];
使用MessageHandler 的好處
1.在JS中寫起來簡單敌厘,不用再用創(chuàng)建URL的方式那么麻煩了。
2.JS傳遞參數(shù)更方便朽合。使用攔截URL的方式傳遞參數(shù)俱两,只能把參數(shù)拼接在后面,如果遇到要傳遞的參數(shù)中有特殊字符曹步,如&宪彩、=、讲婚?等尿孔,必須得轉換,否則參數(shù)解析肯定會出錯筹麸。?
例如傳遞的url是這樣的:?
http://www.baidu.com/share/openShare.htm?share_uuid=shdfxdfdsfsdf&name=1234556?
使用攔截URL 的JS調(diào)用方式
loadURL("haleyAction://shareClick?title=分享的標題&content=分享的內(nèi)容&url=鏈接地址&imagePath=圖片地址"); }
將上面的url 放入鏈接地址這里后活合,根本無法區(qū)分share_uuid是其他參數(shù),還是url里附帶的參數(shù)物赶。?
但是使用MessageHandler 就可以避免特殊字符引起的問題白指。
更詳細的使用步驟還是去工程中查看吧。地址:JS_OC_MessageHandler
版權聲明:本文為博主原創(chuàng)文章酵紫,轉載請注明出處告嘲。 https://blog.csdn.net/u011619283/article/details/52135988