使用WKWebView遇見的那些坑
iOS8之后出了WKWebView,據說加載速度和內存占用情況都甩UIWebView好幾條街,鑒于我們公司的項目用到挺多的webView,于是簡單的調研下決定用WKWebView替換UIWebView。WKWebView的使用方法不多少,相信網上所有的都比我講得好,簡單說下我在使用過程中遇到的坑,以及“復雜”的心路歷程,相信不少人應該也遇到過這種情況
1.三個相關代理WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler。
我學習新東西的習慣是直接看頭文件和露出來的接口,簡單看下注釋,然后直接用,為此多走了不少彎路
WKNavigationDelegate,只提一個方法,
//相當于UIWebView的shouldStartLoadWithRequest,其中decisionHandler一定要實現,否則不執行
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
WKUIDelegate
支持alert彈出框,confirm選擇框,TextInput輸入框,如果不實現此代理中相應的方法,直接點擊是沒有特別反應的,要特別注意。
//alert彈出
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
//confirm選擇框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
//text Input輸入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;
WKScriptMessageHandler
這是JS調用native的代理。native調用JS與UIWebView大同小異,在此不多說。
UIWebView中,JS調用native的方法還是比較好理解的,采用JSContext的形式
JSContext *jsContext = (JSContext *)[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
jsContext[@"jsCallApp"] = self.jsCallApp;
注意WKScriptMessageHandler是WKUserContentController要遵循的協議,附上初始化方法
NSString * name = @"jsCallApp";
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
//遵循協議
[userContentController addScriptMessageHandler:self name:name];
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userContentController;
_webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
_webView.UIDelegate = self;
_webView.navigationDelegate = self;
//加載的本地html文件,便于修改
NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"html"];
NSURL *url = [NSURL fileURLWithPath:path];
[_webView loadFileURL:url allowingReadAccessToURL:url];
[self.view addSubview:_webView];
實現協議方法:注意此方法是request的
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSString *methods = [NSString stringWithFormat:@"%@:", message.body];
SEL selector = NSSelectorFromString(methods);
if ([self respondsToSelector:selector]) {
} else {
NSLog(@"未實行方法:%@", methods);
}
}
JS端必須配合來寫,前端必須用
window.webkit.messageHandlers.jsCallApp.postMessage(null);
來喚起app的方法,其中jsCallApp是對應的name,postMessage中傳參數。
對于更新過很多版本的app來說,考慮實際情況,如果有這種復雜的js與app之間互相調用的話,前端必須考慮判斷版本號,判斷安卓還是iOS,或者安卓跟著做相應的修改,總之還是挺復雜的,如果速度還過得去,也不崩潰的話建議別修改了,如果你的前端和安卓好說話,修改也行。如果不涉及交互,那還是非常建議替換的
還有一個問題就是,對于html動畫特別多的頁面,WKWebView有時候比UIWebView還卡頓,至今未解決,也不知道是什么原因,歡迎知道的大神留言指導。
來自:http://www.jianshu.com/p/39f3ef174835