问题产生背景:
新开发的页面中有一部分的界面是需要展示后端接口返回的HTML代码,包括文字和图片。所以就自然而然的要使用iOS原生的WebKit. 鉴于Xcode 8发布以后,编译器支持的最低版本(Deployment Target)也变为iOS8。因此放弃了UIWebView, 直接使用WKWebView(何况苹果宣称WKWebView的性能相比UIWebView有了极大的提升)。
坑一:获取不到WKWebView的高度
获取方法:在WKWebView加载成功的代理方法里获取WKWebView的UIScrollView的contentSize
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
self.webViewContentHeight = self.webView.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 (!self.webView.isLoading) {
if([keyPath isEqualToString:@"scrollView.contentSize"])
{
self.webViewContentHeight = self.webView.scrollView.contentSize.height;
CGRect frame = self.webView.frame;
frame.size.height = self.webViewContentHeight;
self.webView.frame = frame;
[self.webView sizeToFit];
}
}
}
Bingo! 完美取到WKWebView的height.
坑二:移除KVO的keypath时,程序crash。
- (void)dealloc {
[self.webView removeObserver:self forKeyPath:@"scrollView.contentSize" context:nil];
}
这种情况通常出现在对同一个keypath进行两次remove,如父类中有一个kvo, 父类在dealloc的时候remove一次,子类dealloc的时候又remove一词。看到这里想必大家都已经知道解决思路了吧?那就是区分父类和子类的KVO,回头看一下发现addObserver和removeObserver中都有一个context参数,没错,这个参数就可以用来标记我们自己添加的KVO。
[self.webView addObserver:self forKeyPath:@"scrollView.contentSize" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"DJWebKitContext"];
- (void)dealloc {
[self.webView removeObserver:self forKeyPath:@"scrollView.contentSize" context:@"DJWebKitContext"];
}
运行一下,退出页面的时候果然不会crash了