一、基本的使用方法
<p>介紹:
? ? ? ?WKWebView是蘋果推出的框架,性能比UIWebView更優。
首先上DEMO
WKWebView有兩個delegate,WKUIDelegate
和 WKNavigationDelegate
。
WKNavigationDelegate
主要處理一些跳轉、加載處理操作,
WKUIDelegate
主要處理JS腳本,確認框,警告框等。因此WKNavigationDelegate
更加常用。</p>
// 1.配置環境
WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
userContentController =[[WKUserContentController alloc]init];
configuration.userContentController = userContentController;
wkWebView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) configuration:configuration];
// 2.注冊方法(必要設置,不然WKWebView會無法釋放)
WKDelegateController * delegateController = [[WKDelegateController alloc]init];
delegateController.delegate = self;
// 有添加一定有移除,成對出現
[userContentController addScriptMessageHandler:delegateController name:@"NativeMethod"];
[self.view addSubview:wkWebView];
wkWebView.UIDelegate = self;
wkWebView.navigationDelegate = self;
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
// 根據URL創建請求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setTimeoutInterval:15];
[wkWebView loadRequest:request];
常用的代理方法
WKNavigationDelegate
方法較為常用
// 頁面開始加載時調用
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
}
// 當內容開始返回時調用
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
}
// 頁面加載完成之后調用
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
}
// 頁面加載失敗時調用
-(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{
}
// 接收到服務器跳轉請求之后調用
-(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
}
// 在收到響應后,決定是否跳轉
-(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
NSLog(@"%@",navigationResponse.response.URL.absoluteString);
//允許跳轉
decisionHandler(WKNavigationResponsePolicyAllow);
//不允許跳轉
//decisionHandler(WKNavigationResponsePolicyCancel);
}
// 在發送請求之前,決定是否跳轉
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSLog(@"%@",navigationAction.request.URL.absoluteString);
//允許跳轉
decisionHandler(WKNavigationActionPolicyAllow);
//不允許跳轉
//decisionHandler(WKNavigationActionPolicyCancel);
}
WKUIDelegate
// 創建一個新的WebView
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
return [[WKWebView alloc]init];
}
// 輸入框
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{
completionHandler(@"http");
}
// 確認框
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
completionHandler(YES);
}
// 警告框
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
NSLog(@"%@",message);
completionHandler();
}
-(void)dealloc{
//這里需要注意,前面增加過的方法一定要remove掉。
[userContentController removeScriptMessageHandlerForName:@"NativeMethod"];
}
WKScriptMessageHandler
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
}
// 創建新的控制器設置代理(解決不能釋放的問題)
@protocol WKDelegate <NSObject><br>
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
@end
@interface WKDelegateController : UIViewController <WKScriptMessageHandler>
@property (weak , nonatomic) id<WKDelegate> delegate;
@end
.m文件中的實現
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
if ([self.delegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) {
[self.delegate userContentController:userContentController didReceiveScriptMessage:message];
}
}
關于session 同步 cookies的問題
#### 1.基本配置
NSMutableString *cookies = [NSMutableString string];
WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[cookies copy]
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:NO];
[userContentController addUserScript:cookieScript];
// 一下兩個屬性是允許H5視屏自動播放,并且全屏,可忽略
configuration.allowsInlineMediaPlayback = YES;
configuration.mediaPlaybackRequiresUserAction = NO;
// 全局使用同一個processPool
configuration.processPool = [[WKWebKitSupport sharedSupport] processPool];
configuration.userContentController = userContentController;
#### 2.保存到本地
// 在收到響應后,決定是否跳轉<br>
-(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
NSLog(@"%@",navigationResponse.response.URL.absoluteString);
NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
// 獲取cookie,并設置到本地
NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
for (NSHTTPCookie *cookie in cookies) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
//允許跳轉
decisionHandler(WKNavigationResponsePolicyAllow);
//不允許跳轉
//decisionHandler(WKNavigationResponsePolicyCancel);
}
#### 3.在開始請求時注入
NSURL *url = [NSURL URLWithString:urlString];
NSMutableString *cookies = [NSMutableString string];
NSMutableURLRequest *requestObj = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
// 一般都只需要同步JSESSIONID,可視不同需求自己做更改
NSString * JSESSIONID;
// 獲取本地所有的Cookie
NSArray *tmp = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
for (NSHTTPCookie * cookie in tmp) {
if ([cookie.name isEqualToString:@"JSESSIONID"]) {
JSESSIONID = cookie.value;
break;
}
}
if (JSESSIONID.length) {
// 格式化Cookie
[cookies appendFormat:@"JSESSIONID=%@;",JSESSIONID];
}
// 注入Cookie
[requestObj setValue:cookies forHTTPHeaderField:@"Cookie"];
// 加載請求
[self.wk_webView loadRequest:requestObj];
新增撥打電話和彈窗
// 在發送請求之前,決定是否跳轉<br>
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSLog(@"%@",navigationAction.request.URL.absoluteString);
// 撥打電話
NSURL *URL = navigationAction.request.URL;
NSString *scheme = [URL scheme];
UIApplication *app = [UIApplication sharedApplication];
// 打電話
if ([scheme isEqualToString:@"tel"]) {
if ([app canOpenURL:URL]) {
[app openURL:URL];
// 一定要加上這句,否則會打開新頁面
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
// 打開appstore
if ([URL.absoluteString containsString:@"ituns.apple.com"]) {
if ([app canOpenURL:URL]) {
[app openURL:URL];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
//允許跳轉
decisionHandler(WKNavigationActionPolicyAllow);
//不允許跳轉
//decisionHandler(WKNavigationActionPolicyCancel);
}
#### 警告框
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
NSLog(@"%@",message);
// js 里面的alert實現,如果不實現,網頁的alert函數無效 ,
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
completionHandler();
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){
completionHandler();
}]];
[self presentViewController:alertController animated:YES completion:^{}];
// 要實現
// completionHandler();
}
#### 確認框
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
// js 里面的alert實現,如果不實現,網頁的alert函數無效 ,
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
completionHandler(YES);
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){
completionHandler(NO);
}]];
[self presentViewController:alertController animated:YES completion:^{}];
}
適配HTML5頁面的問題
// 內容視圖自適應大小
NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
[userContentController addUserScript:wkUScript];