使用WKWebView遇見的那些坑

iOS8之后出了WKWebView,據(jù)說加載速度和內(nèi)存占用情況都甩UIWebView好幾條街,鑒于我們公司的項(xiàng)目用到挺多的webView,于是簡(jiǎn)單的調(diào)研下決定用WKWebView替換UIWebView。WKWebView的使用方法不多少,相信網(wǎng)上所有的都比我講得好,簡(jiǎn)單說下我在使用過程中遇到的坑,以及“復(fù)雜”的心路歷程,相信不少人應(yīng)該也遇到過這種情況

1.三個(gè)相關(guān)代理WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler。
我學(xué)習(xí)新東西的習(xí)慣是直接看頭文件和露出來的接口,簡(jiǎn)單看下注釋,然后直接用,為此多走了不少?gòu)澛?br> WKNavigationDelegate,只提一個(gè)方法,

//相當(dāng)于UIWebView的shouldStartLoadWithRequest,其中decisionHandler一定要實(shí)現(xiàn),否則不執(zhí)行
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

WKUIDelegate
支持alert彈出框,confirm選擇框,TextInput輸入框,如果不實(shí)現(xiàn)此代理中相應(yīng)的方法,直接點(diǎn)擊是沒有特別反應(yīng)的,要特別注意。

//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調(diào)用native的代理。native調(diào)用JS與UIWebView大同小異,在此不多說。
UIWebView中,JS調(diào)用native的方法還是比較好理解的,采用JSContext的形式

JSContext *jsContext = (JSContext *)[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
jsContext[@"jsCallApp"] = self.jsCallApp;

注意WKScriptMessageHandler是WKUserContentController要遵循的協(xié)議,附上初始化方法

    NSString * name = @"jsCallApp";
    WKUserContentController *userContentController = [[WKUserContentController alloc] init];
    //遵循協(xié)議
    [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];

實(shí)現(xiàn)協(xié)議方法:注意此方法是request的

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSString *methods = [NSString stringWithFormat:@"%@:", message.body];
    SEL selector = NSSelectorFromString(methods);
    if ([self respondsToSelector:selector]) {
       
    } else {
        NSLog(@"未實(shí)行方法:%@", methods);
    }
}

JS端必須配合來寫,前端必須用
window.webkit.messageHandlers.jsCallApp.postMessage(null);
來喚起app的方法,其中jsCallApp是對(duì)應(yīng)的name,postMessage中傳參數(shù)。

對(duì)于更新過很多版本的app來說,考慮實(shí)際情況,如果有這種復(fù)雜的js與app之間互相調(diào)用的話,前端必須考慮判斷版本號(hào),判斷安卓還是iOS,或者安卓跟著做相應(yīng)的修改,總之還是挺復(fù)雜的,如果速度還過得去,也不崩潰的話建議別修改了,如果你的前端和安卓好說話,修改也行。如果不涉及交互,那還是非常建議替換的
還有一個(gè)問題就是,對(duì)于html動(dòng)畫特別多的頁面,WKWebView有時(shí)候比UIWebView還卡頓,至今未解決,也不知道是什么原因,歡迎知道的大神留言指導(dǎo)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容