隨著iOS10的出現,大部分應用都已經拋棄了iOS7的支持,那么將UIWebView
替換為WKWebView
的工作也就提上了日程。畢竟UIWebView
的占用內存大,而且存在泄漏問題,包括對js的支持也是不如WKWebView
的,所以大部分的UIWebView
都應該替換為WKWebView
。
由于我們的工程對js只進行了簡單的支持和調用,并沒有太多復雜的交互,這里就不對WKUIDelegate
進行說明了,畢竟我也不是很清楚。這里簡單說一下我在替換過程中遇到的一些問題吧:
彈出的鏈接替換
在UIWebViewDelegate中,shouldStartLoadWithRequest
方法里可以獲取到對應的NSURLRequest,進行處理,然后返回YES
/NO
;而在WKNavigationDelegate
中,對應的方法應該是decidePolicyForNavigationAction
,可以在navigationAction中獲取到對應的request,然后進行處理,不過沒有返回值,而是使用回調方法進行處理。-
初始鍵盤彈出
在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的答案 -
JavaScript
的調用
看起來和UIWebView
的調用差不多,一個方法是stringByEvaluatingJavaScriptFromString
,另一個是evaluateJavaScript
,但其實是完全不同的,主要就在于一個是同步調用,另一個是異步調用。
如果原來的代碼已經使用了UIWebView
,那么在修改WKWebView
時一定要注意,因為異步調用是不可以同時調用多個js
方法的,否則執行順序將無法保證。
下面寫出我把異步調用修改為同步調用的方法,是實現在了WKWebView
的category
里面:- (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
之后,性能上確實提高了,比以前流暢多了。