iOS8之后,蘋果推出了WebKit這個框架,用來替換原有的UIWebView,新的控件優(yōu)點(diǎn)多多,不一一敘述。由于一直在適配iOS7,就沒有去替換,現(xiàn)在仍掉了iOS7,以為很簡單的就替換過來了,然而在替換的過程中,卻遇到了很多坑。
WKWebView使用及注意點(diǎn)
WKWebView只能用代碼創(chuàng)建,而且自身就支持了右滑返回手勢allowsBackForwardNavigationGestures和加載進(jìn)度estimatedPRogress等一些UIWebView不具備卻非常好用的屬性。在創(chuàng)建的時候,指定初始化方法中要求傳入一個WKWebViewConfiguration對象,一般我們使用默認(rèn)配置就好,但是有些地方是要根據(jù)自己的情況去做更改。比如,配置中的allowsInlineMediaPlayback這個屬性,默認(rèn)為NO,如果不做更改,網(wǎng)頁中的視頻將彈出一個全屏的控制器來播放,設(shè)置為YES,將內(nèi)嵌在網(wǎng)頁中播放。更改User-Agent
有時我們需要在User-Agent添加一些額外的信息,這時就要更改默認(rèn)的User-Agent.self.wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero];//獲取默認(rèn)User-Agent[self.wkWebView evaluatejavaScr需要注意的是App內(nèi)所有Web請求的User-Agent全部被修改。在iOS9,WKWebView提供了一個非常便捷的屬性去更改User-Agent,就是customUserAgent屬性。這樣使用起來不僅方便,也不會全局更改User-Agent,可惜的是iOS9才有,如果適配iOS8,還是要使用上面的方法。用來追蹤加載過程(頁面開始加載、加載完成、加載失?。┑姆椒ǎ? // 頁面開始加載時調(diào)用 -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation; // 當(dāng)內(nèi)容開始返回時調(diào)用 -(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation; // 頁面加載完成之后調(diào)用 -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation; // 頁面加載失敗時調(diào)用 -(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;
頁面跳轉(zhuǎn)的代理方法:
// 接收到服務(wù)器跳轉(zhuǎn)請求之后調(diào)用 -(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation; // 在收到響應(yīng)后,決定是否跳轉(zhuǎn) -(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler; // 在發(fā)送請求之前,決定是否跳轉(zhuǎn) -(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
JS在調(diào)用OC注冊方法的時候要用下面的方式:
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)注意:name(方法名)是放在中間的,messageBody只能是一個對象,如果要傳多個值,需要封裝成數(shù)組,或者字典。整個示例如下:
//OC注冊供JS調(diào)用的方法[[_webView configuration].userContentController addScriptMessageHandler:self name:@"closeMe"];//OC在JS調(diào)用方法做的處理- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"JS 調(diào)用了 %@ 方法,傳回參數(shù) %@",message.name,message.body);}//JS調(diào)用 window.webkit.messageHandlers.closeMe.postMessage(null); 如果你在self的dealloc打個斷點(diǎn),會發(fā)現(xiàn)self沒有釋放!這顯然是不行的!谷歌后看到一種解決方法,如下:
@interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;@end@implementation WeakScriptMessageDelegate- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate{ self = [super init]; if (self) { _scriptDelegate = scriptDelegate; } return self;}- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];}@end思路是另外創(chuàng)建一個代理對象,然后通過代理對象回調(diào)指定的self,
WKUserContentController *userContentController = [[WKUserContentController alloc] init]; [userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"closeMe"];運(yùn)行代碼,self釋放了,WeakScriptMessageDelegate卻沒有釋放啊啊??! 還需在self的dealloc里面 添加這樣一句代碼:
[[_webView configuration].userContentController removeScriptMessageHandlerForName:@"closeMe"];新聞熱點(diǎn)
疑難解答