WKWebView的使用(一)

隨著iOS10的出現,大部分應用都已經拋棄了iOS7的支持,那么將UIWebView替換為WKWebView的工作也就提上了日程。畢竟UIWebView的占用內存大,而且存在泄漏問題,包括對js的支持也是不如WKWebView的,所以大部分的UIWebView都應該替換為WKWebView。

由于我們的工程對js只進行了簡單的支持和調用,并沒有太多復雜的交互,這里就不對WKUIDelegate進行說明了,畢竟我也不是很清楚。這里簡單說一下我在替換過程中遇到的一些問題吧:

  1. 彈出的鏈接替換
    在UIWebViewDelegate中,shouldStartLoadWithRequest方法里可以獲取到對應的NSURLRequest,進行處理,然后返回YES/NO;而在WKNavigationDelegate中,對應的方法應該是decidePolicyForNavigationAction,可以在navigationAction中獲取到對應的request,然后進行處理,不過沒有返回值,而是使用回調方法進行處理。

  2. 初始鍵盤彈出
    UIWebView中,有一個屬性keyboardDisplayRequiresUserAction,設置為NO時就可以在頁面剛加載時直接彈出鍵盤;
    WKWebView中,是沒有這個屬性的,如果要實現類似的功能,就必須替換WKWebView中相應的方法,代碼如下:

    static void (*originalIMP)(id self, SEL _cmd, void* arg0, BOOL arg1, BOOL arg2, id arg3) = NULL;
    void interceptIMP (id self, SEL _cmd, void* arg0, BOOL arg1, BOOL arg2, id arg3) {
       originalIMP(self, _cmd, arg0, TRUE, arg2, arg3);
    }
    void setWkWebViewShowKeybord() {
      Class cls = NSClassFromString(@"WKContentView");
       SEL originalSelector = NSSelectorFromString(@"_startAssistingNode:userIsInteracting:blurPreviousNode:userObject:");  
       Method originalMethod = class_getInstanceMethod(cls, originalSelector);
       IMP impOvverride = (IMP) interceptIMP;
       originalIMP = (void *)method_getImplementation(originalMethod);
       method_setImplementation(originalMethod, impOvverride);
    }
    

    需要調用?函數setWkWebViewShowKeybord,才可以實現該功能;需要特別注意的是,該函數只能調用一次,否則會導致循環調用,程序崩潰。上述代碼引用自stackoverflow的答案

  3. JavaScript的調用
    看起來和UIWebView的調用差不多,一個方法是stringByEvaluatingJavaScriptFromString,另一個是evaluateJavaScript,但其實是完全不同的,主要就在于一個是同步調用,另一個是異步調用。
    如果原來的代碼已經使用了UIWebView,那么在修改WKWebView時一定要注意,因為異步調用是不可以同時調用多個js方法的,否則執行順序將無法保證。
    下面寫出我把異步調用修改為同步調用的方法,是實現在了WKWebViewcategory里面:

    - (id)syncEvalJavascriptString:(NSString *)jsCode {
        __block id returnValue = nil;
        __block BOOL finished = NO;
        [self evaluateJavaScript:jsCode completionHandler:^(id _Nullable result, NSError * _Nullable error) {
            returnValue = result;
            finished = YES;
        }];
        while (!finished) {
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
        return returnValue;
    }
    

    需要注意的就是NSRunLoop那里不可以使用dispatch_semaphore_t信號量代替,會導致永久等待的,已經實測過了。

目前我使用到的也就這些了,后續如果有對于WKWebView的更多了解的話,在增加吧。不過替換成了WKWebView之后,性能上確實提高了,比以前流暢多了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容