1、UIWebView 有属性 scalespageToFit,设置为YES,可以自动对页面进行缩放以适应屏幕,WKWebView怎么做可以实现自动缩放网页比例 ?
解决办法:使用scrollView的代理
//但如果这么写了的话, 需要在dealloc中把代理置nil: _wkWebView.scrollView.delegate = nil;否则会崩溃
_wkWebView.scrollView.delegate = self;
之前有引用到WKWebview,为使用方便将WKWebview设为了成员变量,然后又设置了该成员变量的scrollview的属性的代理为当前视图控制器,然后就出现了问题,每次push时候从新创建时候总会访问之前的内存,然后报错说访问了一块已经释放掉的内存,pop出栈的时候会崩溃,这样一直找不到问题的存在,后来才知道强引用了scrollview,代理释放不掉,所以会报错,解决办法,在dealloc函数或者viewwillappear等函数中将代理设为nil就解决了
2、获取不到WKWebView的高度
获取方法:在WKWebView加载成功的代理方法里获取WKWebView的UIScrollView的contentSize
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
webViewContentHeight = _wkWebView.scrollView.contentSize.height;
}
运行后,发现获取不到contentSize, 打印结果显示(width = 0, height =0).
解决办法:使用KVO监听WKWebView的contentSize
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (!_wkWebView.isLoading) {
if([keyPath isEqualToString:@"scrollView.contentSize"])
{
webViewContentHeight = _wkWebView.scrollView.contentSize.height;
CGRect frame = _wkWebView.frame;
frame.size.height = webViewContentHeight;
_wkWebView.frame = frame;
[_wkWebView sizeToFit];
}
}
}
也可以用JS来获取:
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
NSLog(@"%f",_webView.scrollView.contentSize.height);
MJWeakSelf
[_wkWebView evaluateJavaScript:@"document.body.offsetHeight;" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
//获取页面高度,并重置webview的frame
float height = [result doubleValue];
CGRect frame = weakSelf.wkWebView.frame;
frame.size.height = webViewContentHeight;
weakSelf.wkWebView.frame = frame;
[weakSelf.wkWebView sizeToFit];
}];
}
3、移除KVO的keypath时,程序crash
- (void)dealloc {
[_wkWebView removeObserver:self forKeyPath:@"scrollView.contentSize" context:nil];
}
这种情况通常出现在对同一个keypath进行两次remove,如父类中有一个kvo, 父类在dealloc的时候remove一次,子类dealloc的时候又remove一次。
解决办法:用Observer中的context参数来做标记,避免跟其他的重复
[_wkWebView addObserver:self forKeyPath:@"scrollView.contentSize" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"wkContext"];
- (void)dealloc {
[_wkWebView removeObserver:self forKeyPath:@"scrollView.contentSize" context:@"wkContext"];
}
4、WKWebView 白屏问题
在 UIWebView 上当内存占用太大的时候,App Process 会 crash;而在 WKWebView 上当总体的内存占用比较大的时候,WebContent Process 会 crash,从而出现白屏现象。
解决办法:借助 WKNavigtionDelegate
当 WKWebView 总体内存占用过大,页面即将白屏的时候,系统会调用上面的回调函数,我们在该函数里执行[webView reload](这个时候 webView.URL 取值尚不为 nil)解决白屏问题。在一些高内存消耗的页面可能会频繁刷新当前页面,H5侧也要做相应的适配操作。
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));
但并不是所有白屏都会掉用上面方法,可以在 viewWillAppear 的时候检测 webView.title 是否为空来 reload 页面。
5、WKWebView 页面样式问题
如果H5页面有透明导航、透明导航下拉刷新、全屏等需求,而webView 是从(0, 0)开始布局,我们可以通过调整webView.scrollView.contentInset 来适配特殊导航栏需求,但这个修改就会影响webView.scrollView.contentSize.height,从而导致H5页面偏移问题。
解决办法:调整webView的布局方式,尽量不调整webView.scrollView.contentInset。如果不得不调整可以用下面方法让H5正常显示:
/**设置contentInset值后通过调整webView.frame让页面恢复正常显示
*参考:http://km.oa.com/articles/show/277372
*/
webView.scrollView.contentInset = UIEdgeInsetsMake(a, 0, 0, 0);
webView.frame = CGRectMake(webView.frame.origin.x, webView.frame.origin.y, webView.frame.size.width, webView.frame.size.height - a);
6、JS调用window.alert()函数引起的crash
错误信息如下:
...
28 UIKit 0x0000000190513360 UIApplicationMain + 208
29 Qzone 0x0000000101380570 main (main.m:181)
30 libdyld.dylib 0x00000001895205b8 _dyld_process_info_notify_release + 36
Completion handler passed to -[QZWebController webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:] was not called
从 crash 可以看出是 WKWebView 回调函数: runJavaScriptAlertPanelWithMessage中completionHandler 没有被调用导致的。
出现情况可能是WKWebView 退出的时候,JS刚好执行了window.alert(), alert 框可能弹不出来,completionHandler 最后没有被执行,导致 crash;另一种情况是在 WKWebView 一打开,JS就执行window.alert(),这个时候由于 WKWebView 所在的 UIViewController 出现(push或present)的动画尚未结束,alert 框可能弹不出来,completionHandler 最后没有被执行,导致 crash。
解决办法如下:
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
if (/*UIViewController of WKWebView has finish push or present animation*/) {
completionHandler();
return;
}
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { completionHandler(); }]];
if (/*UIViewController of WKWebView is visible*/)
[self presentViewController:alertController animated:YES completion:^{}];
else
completionHandler();
}
7、视频自动播放
WKWebView 需要通过WKWebViewConfiguration.mediaPlaybackRequiresUserAction
设置是否允许自动播放,但一定要在 WKWebView 初始化之前设置,在 WKWebView 初始化之后设置无效。
网友评论