WKWebView支持ios8之后,優(yōu)點:
1.更多的支持HTML5的特性
2.官方宣稱的高達60fps的滾動刷新率以及內(nèi)置手勢
3.Safari相同的JavaScript引擎
4.占用更少的內(nèi)存
一、基本使用
WKWebView有兩個delegate,WKUIDelegate和WKNavigationDelegate。WKNavigationDelegate主要處理一些跳轉(zhuǎn)、加載處理操作,WKUIDelegate主要處理JS腳本,確認框,警告框等。因此WKNavigationDelegate更加常用。
1.導入頭文件#import<WebKit/WebKit.h>
2.相對應的使用方法:
備注:WKWebViewConfiguration和WKPreferences中有很多屬性可以對webview初始化進行設置
?WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
? ? config.selectionGranularity = WKSelectionGranularityDynamic;
? ? config.allowsInlineMediaPlayback = YES;
? ? WKPreferences *preferences = [WKPreferences new];
? ? //是否支持JavaScript
? ? preferences.javaScriptEnabled = YES;
? ? //不通過用戶交互,是否可以打開窗口
? ? preferences.javaScriptCanOpenWindowsAutomatically = YES;
? ? config.preferences = preferences;
? ? WKWebView *webview = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight - 64) configuration:config];
? ? [self.view addSubview:webview];
? ? /* 加載服務器url的方法*/
? ? NSString *url = @"https://www.baidu.com";
? ? NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
? ? [webview loadRequest:request];
? ? webview.navigationDelegate = self;
? ? webview.UIDelegate = self;
遵循的協(xié)議和實現(xiàn)的協(xié)議方法:
#pragma mark - WKNavigationDelegate
/* 頁面開始加載 */
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
}
/* 開始返回內(nèi)容 */
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
}
/* 頁面加載完成 */
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
}
/* 頁面加載失敗 */
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{
}
/* 在發(fā)送請求之前,決定是否跳轉(zhuǎn) */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
? ? //允許跳轉(zhuǎn)
? ? decisionHandler(WKNavigationActionPolicyAllow);
? ? //不允許跳轉(zhuǎn)
? ? //decisionHandler(WKNavigationActionPolicyCancel);
}
/* 在收到響應后,決定是否跳轉(zhuǎn) */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
? ? NSLog(@"%@",navigationResponse.response.URL.absoluteString);
? ? //允許跳轉(zhuǎn)
? ? decisionHandler(WKNavigationResponsePolicyAllow);
? ? //不允許跳轉(zhuǎn)
? ? //decisionHandler(WKNavigationResponsePolicyCancel);
}
#pragma mark - WKUIDelegate
// 創(chuàng)建一個新的WebView
- (WKWebView*)webView:(WKWebView*)webView createWebViewWithConfiguration:(WKWebViewConfiguration*)configuration forNavigationAction:(WKNavigationAction*)navigationAction windowFeatures:(WKWindowFeatures*)windowFeatures{
return[[WKWebViewalloc]init];
}
// 輸入框
- (void)webView:(WKWebView*)webView runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt defaultText:(nullableNSString*)defaultText initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void(^)(NSString* __nullableresult))completionHandler{?
?completionHandler(@"http");
}// 確認框
- (void)webView:(WKWebView*)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void(^)(BOOLresult))completionHandler{
?completionHandler(YES);
}
// 警告框
- (void)webView:(WKWebView*)webView runJavaScriptAlertPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void(^)(void))completionHandler{
NSLog(@"%@",message); completionHandler();
}
url中文處理
有時候我們加載的URL中可能會出現(xiàn)中文,需要我們手動進行轉(zhuǎn)碼,但是同時又要保證URL中的特殊字符保持不變,那么我們就可以使用下面的方法(方法放到了NSString中的分類中):
- (NSURL *)url{
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
? ? return [NSURL URLWithString:(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, (CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL,kCFStringEncodingUTF8))];
#pragma clang diagnostic pop
}
獲取h5中的標題 和進度條
在初始化wenview時,添加兩個觀察者分別用來監(jiān)聽webview 的estimatedProgress和title屬性:
webview.navigationDelegate = self;
webview.UIDelegate = self;
[webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
[webview addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
實現(xiàn)觀察者的回調(diào)方法:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
? ? if ([keyPath isEqualToString:@"estimatedProgress"]) {
//進度條設置
? ? ? ? if ([change[@"new"] floatValue] <[change[@"old"] floatValue]) {
? ? ? ? ? ? return;
? ? ? ? }
//進度條設置? ? ? ? if ([change[@"new"]floatValue] == 1.0) {
? ? ? ? ? ? dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//進度條設置
? ? ? ? ? ? });
? ? ? ? }
? ? }else if ([keyPath isEqualToString:@"title"]){
//標題設置
? ? }
}
添加userAgent信息
在Appdelegate中添加一個WKWebview的屬性,啟動app時直接,為該屬性添加userAgent:
- (void)setUserAgent {
? ? _webView = [[WKWebView alloc] initWithFrame:CGRectZero];
? ? [_webView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {
? ? ? ? if (error) { return; }
? ? ? ? NSString *userAgent = result;
? ? ? ? if (![userAgent containsString:@"/mobile-iOS"]) {
? ? ? ? ? ? userAgent = [userAgent stringByAppendingString:@"/mobile-iOS"];
? ? ? ? ? ? NSDictionary *dict = @{@"UserAgent": userAgent};
? ? ? ? ? ? [TKUserDefaults registerDefaults:dict];
? ? ? ? }
? ? }];
}
原生JS交互
(一)JS調(diào)用原生方法
在WKWebView中實現(xiàn)與JS的交互還需要實現(xiàn)另外一個代理方法:WKScriptMessageHandler
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController
? ? ? didReceiveScriptMessage:(WKScriptMessage *)message
備注:JS只能向原生傳遞一個參數(shù),所以如果有多個參數(shù)需要傳遞,可以讓JS傳遞對象或者JSON字符串即可。
(二)原生調(diào)用JS方法
[webview evaluateJavaScript:“JS語句” completionHandler:^(id _Nullable data, NSError * _Nullable error) {
?}];