wkwebview與js通訊學習總結(一)
- EvaluateJavaScript方法為非同步
- - UIWebview: 中是同步執行的,直接呼叫 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;方法返回執行結果
- - WKWebView改為了```block```的方式進行值返回,並且該方法的執行是非同步的- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler;
延伸:執行JS方法的使用場景之一,就是獲取當前webview的title,```WKWebView```提供了新屬性title,如果是想獲取title,可以直接使用```WKWebView```的title屬性.
- cookie設定方式不同
- - UIWebView:NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];[storage setCookie:cookieKey value:cookieValue];通過該方式設定的,為全域性的cookie,專案中任意的```UIWebView```均攜帶一樣的cookie.設定之後不需要做額外的操作.
- - WKWebView網頁將不再能獲取預設的cookie,如果需要攜帶cookie,需要做一些操作:
注入cookie
獲取當前的userContentController WKUserContentController *userContentController = self.wkWebView.configuration.userContentController;
注入scrpit: WKUserScript *script = [[WKUserScript alloc] initWithSource:cookieValue injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[userContentController addUserScript:script];
注意:注入script時引數indectionTime有兩個可選項```WKUserScriptInjectionTimeAtDocumentStart```和```WKUserScriptInjectionTimeAtDocumentEnd```,
我們看一下官方文件對於這兩個選項的解釋:
```WKUserScriptInjectionTimeAtDocumentStart``` : 注入時機為document的元素生成之後,其他內容load之前.
```WKUserScriptInjectionTimeAtDocumentEnd``` : 注入時機為document全部load完成,任意子資源load完成之前.
一般情況下,如果想盡早注入cookie,在```WKUserScriptInjectionTimeAtDocumentStart```時完成即可,但是有一種特殊情況,即目前的診療圈為後端渲染,資料請求依賴cookie中的```sessionKey```,而前端頁面的元素依賴後端返回的資料,因此,有一個問題,即cookie是在頁面元素生成之後注入的,而在這之前,後端需要獲取cookie,那麼應該怎麼辦呢??
在requestHeader內注入cookie
NSString *cookie = @"cookieKey1=cookieValue1;cookieKey2=cookieValue2";```
[mutableRequest addValue:cookie forHTTPHeaderField:@"Cookie"];
這樣在網路請求開始時,requestHeader將攜帶cookie.
- WKWebView預設禁止了一些跳轉
- UIWebView 開啟ituns.apple.com跳轉到appStore, 撥打電話, 喚起郵箱等一系列操作UIWebView預設支援的.
- WKWebView預設禁止了以上行為,除此之外,js端通過```window.open()```開啟新的網頁的動作也被禁掉了.
如何支援呢?
######可以跳轉appStore或者撥號
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if(webView != self.wkWebView) {
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
UIApplication *app = [UIApplication sharedApplication];
if ([url.scheme isEqualToString:@"tel"])
{
if ([app canOpenURL:url])
{
[app openURL:url];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
if ([url.absoluteString containsString:@"ituns.apple.com"])
{
if ([app canOpenURL:url])
{
[app openURL:url];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
decisionHandler(WKNavigationActionPolicyAllow);
}
######支援window.open()
需要開啟新介面是,WKWebView的代理```WKUIDelegate```方法
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
會攔截到window.open()事件.
只需要我們在在方法內進行處理
if (!navigationAction.targetFrame.isMainFrame) {
[webView loadRequest:navigationAction.request];
}
######支援alert()
WKWebView預設不響應js的alert()事件,如何可以開啟alert許可權呢?
代理```WKUIDelegate```方法
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
將會獲取到alert的資訊,但是不會彈出alert.
在方法內部
[alertController addAction:[UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
completionHandler();
}]];
if ([self.delegate isKindOfClass:[UIViewController class]]) {
UIViewController *controller = (UIViewController *)self.delegate;
[controller presentViewController:alertController animated:YES completion:^{}];
}