WKWebView的使用(一)
随着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
,才可以实现该功能;需要特别注意的是,该函数只能调用一次,否则会导致循环调用,程序崩溃。上述代码引用自*的答案 -
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
之后,性能上确实提高了,比以前流畅多了。