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中相应的方法,代码如下:
```objective-c
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的答案](http://stackoverflow.com/questions/32407185/wkwebview-cant-open-keyboard-for-input-field)

3. `JavaScript`的调用
 > 看起来和`UIWebView`的调用差不多,一个方法是`stringByEvaluatingJavaScriptFromString`,另一个是`evaluateJavaScript`,但其实是完全不同的,主要就在于一个是同步调用,另一个是异步调用。
如果原来的代码已经使用了`UIWebView`,那么在修改`WKWebView`时一定要注意,因为异步调用是不可以同时调用多个`js`方法的,否则执行顺序将无法保证。
下面写出我把异步调用修改为同步调用的方法,是实现在了`WKWebView`的`category`里面:
```objective-c
- (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之后,性能上确实提高了,比以前流畅多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值