????????蘋果公司在2014 WWDC上發(fā)布了iOS8,同時引入了WKWebView來替代傳統(tǒng)的UIWebView÷夂現(xiàn)在的產(chǎn)品也越來越多的使用到webview來實現(xiàn)app內(nèi)部復(fù)雜而又低動效的UI效果。今天我們就來看一下WKWebView的簡單應(yīng)用域庇。
WKWebView的優(yōu)勢:
在性能烁兰、穩(wěn)定性、功能方面有很大提升(最直觀的體現(xiàn)就是加載網(wǎng)頁是占用的內(nèi)存)转晰;
允許JavaScript的Nitro庫加載并使用(UIWebView中限制);
支持了更多的HTML5特性;
官方宣稱的高達60fps的滾動刷新率以及內(nèi)置手勢查邢;
將UIWebViewDelegate與UIWebView重構(gòu)成了14類與3個協(xié)議蔗崎。
????使用WKWebView我們首先引入#import <WebKit/WebKit.h>。下面直接上代碼扰藕。這是一個最簡單的webView的初始化缓苛。
一下是webview的navgationDelegate的各個方法。我們看一下他們的調(diào)用順序邓深。
//網(wǎng)頁加載之前未桥,是否允許開始加載網(wǎng)頁
- (void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler;
{
? ? //1
? ? decisionHandler(WKNavigationActionPolicyAllow);
}
//是否允許加載網(wǎng)頁接受到的收據(jù)
- (void)webView:(WKWebView*)webView decidePolicyForNavigationResponse:(WKNavigationResponse*)navigationResponse decisionHandler:(void(^)(WKNavigationResponsePolicy))decisionHandler
{
? ? //5
? ? decisionHandler(WKNavigationResponsePolicyAllow);
}
//開始接收網(wǎng)頁數(shù)據(jù)
- (void)webView:(WKWebView*)webView didStartProvisionalNavigation:(null_unspecifiedWKNavigation*)navigation
{
? ? //2
}
//收到重定向請求
- (void)webView:(WKWebView*)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecifiedWKNavigation*)navigation
{
? ? //3
}
//加載失敗 (向網(wǎng)頁請求加載數(shù)據(jù)時)
- (void)webView:(WKWebView*)webView didFailProvisionalNavigation:(null_unspecifiedWKNavigation*)navigation withError:(NSError*)error
{
}
//開始加載網(wǎng)頁數(shù)據(jù)
- (void)webView:(WKWebView*)webView didCommitNavigation:(null_unspecifiedWKNavigation*)navigation
{
? ? //6
}
//加載結(jié)束
- (void)webView:(WKWebView*)webView didFinishNavigation:(null_unspecifiedWKNavigation*)navigation
{
? ? //7
}
//加載失敗 (接收網(wǎng)頁數(shù)據(jù)時)
- (void)webView:(WKWebView*)webView didFailNavigation:(null_unspecifiedWKNavigation*)navigation withError:(NSError*)error
{
}
//安全驗證
- (void)webView:(WKWebView*)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge completionHandler:(void(^)(NSURLSessionAuthChallengeDispositiondisposition,NSURLCredential*_Nullablecredential))completionHandler
{
? ? //4 ? 這個方法不經(jīng)常用到,沒有過多的探究芥备。它是用于webview的數(shù)字證書安全驗證冬耿。
? ? completionHandler(NSURLSessionAuthChallengeUseCredential , challenge.proposedCredential);
}
在這里就遇到了wekwebview的第一個坑:如果我們使用了調(diào)用順序中的1和5方法,額哦們就必須實現(xiàn)decisionHandler block门躯。WKNavigationActionPolicy 和 是一個枚舉類型:.Allow //允許 ?.Cancel//取消 ?來控制是否允許網(wǎng)頁的跳轉(zhuǎn)和加載淆党。如果不實現(xiàn),程序會崩潰讶凉。
JS和WKWebView的數(shù)據(jù)交互染乌。
接下來我們看一下JS和WKWebView是如何實現(xiàn)數(shù)據(jù)交互的。
1懂讯、webView調(diào)用JS方法荷憋,很簡單一句話調(diào)用。
? ??[self.webView evaluateJavaScript:@"OCCallJSAction" completionHandler:^(id object, NSError * error) {
? ? }];
2褐望、JS調(diào)用webView的方法勒庄。首先我們用WKWebViewConfiguration的方法初始化webView。
????WKWebViewConfiguration? *configuration? = [[WKWebViewConfiguration alloc]init];
? ? WKUserContentController*userVC? ? ? ? ? ????= [[WKUserContentController alloc]init];
? ? [userVC addScriptMessageHandler:self? ? name:@"JSCallOCAction"];
? ? configuration.userContentController? ? = userVC;
? ? self.webView? ? ? ? ? ? = [[WKWebView alloc]initWithFrame:self.view.bounds
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? configuration:configuration];
? ? self.webView.navigationDelegate? ? ? ? =self;
? ? [self.view addSubview:self.webView];
? ? NSURLRequest*request? = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];
? ? [self.webViewloadRequest:request];
然后實現(xiàn)方法:
- (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message
{
? ? //通過message.name判斷JS的響應(yīng)方法 來決定如何實現(xiàn)瘫里。參數(shù)在message.body实蔽。如果有多個方法可以使用定義多個name或者根據(jù)body區(qū)分實現(xiàn)。
}
注意:addScriptMessageHandler: ?name:方法會循環(huán)引用引發(fā)內(nèi)存泄漏谨读,需要我們特殊處理局装。當(dāng)使用該方法時,你會發(fā)現(xiàn)當(dāng)前控制器退出時劳殖,并不會觸發(fā)dealloc方法铐尚。我們需要調(diào)用userController的removeScriptMessageHandlerForName:方法。
? ? 此前使用在viewWillAppear中調(diào)用add方法哆姻,在viewWillDisappear中調(diào)用remove方法宣增,使控制器釋放。但是此時控制器并不會走dealloc方法矛缨。我們只做一個中間類WeakScriptMessageDelegate爹脾,來實現(xiàn)帖旨。
以下代碼可以直接寫到控制器的.h文件當(dāng)中:
@interface WeakScriptMessageDelegate: NSObject
@property (nonatomic, weak) id scriptDelegate;
- (instancetype)initWithDelegate:(id)scriptDelegate;
@end
以下代碼可以直接寫到控制器的.m文件當(dāng)中:
@implementationWeakScriptMessageDelegate
- (instancetype)initWithDelegate:(id)scriptDelegate {
? ? self= [superinit];
? ? if(self) {
? ? ? ? _scriptDelegate= scriptDelegate;
? ? }
? ? return self;
}
- (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message {
? ? [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}
@end
我們在調(diào)用add方法時使用:
[userVC addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] ?name:@"JSCallOCAction"];
在控制器的dealloc中使用:
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"JSCallOCAction"];
OC捕獲H5的控件行為
? ?如果我們想要捕獲H5中的一些控件行為,我們需要設(shè)置WKWebView的UIDelegate灵妨。self.webView.UIDelegate = self;下面我們來看一下UIDelegate中經(jīng)常用到的幾個方法碉就。
//加載一個新的網(wǎng)頁
- (nullableWKWebView*)webView:(WKWebView*)webView createWebViewWithConfiguration:(WKWebViewConfiguration*)configuration forNavigationAction:(WKNavigationAction*)navigationAction windowFeatures:(WKWindowFeatures*)windowFeatures;
//關(guān)閉網(wǎng)頁 9.0以后可用
- (void)webViewDidClose:(WKWebView*)webView API_AVAILABLE(macosx(10.11), ios(9.0));
//捕獲H5中的Alert行為
- (void)webView:(WKWebView*)webView runJavaScriptAlertPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void(^)(void))completionHandler;
//捕獲H5中的Confirm行為
- (void)webView:(WKWebView*)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void(^)(BOOLresult))completionHandler;
//捕獲H5中的TextInput輸入框行為
- (void)webView:(WKWebView*)webView runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt defaultText:(nullableNSString*)defaultText initiatedByFrame:(WKFrameInfo*)frame completionHandler:(void(^)(NSString*_Nullableresult))completionHandler;
????以上就是WKWebView的簡單應(yīng)用。如果有錯誤的地方歡迎在下方評論區(qū)指出闷串,不同意見大家一起討論下。萬分感謝筋量。