需求:
- 今天遇到一个需求, WKWebView 高度需要固定, 根据 WKWebView 加载进度的变化, 实时更新高度,
在实际开发中, 有很多情况需要通过数据的变化去更新 UI 高度的, 比如 tableView 的 header, webView 的高度.
方案:
- 监听 WKWebView 滚动区域变化
class ViewController: UIViewController {
// 需要被 observer 持有, 会随持有者被释放
var observation: NSKeyValueObservation?
private lazy var webView: WKWebView = {
let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true
let wv = WKWebView(frame: , configuration: config)
wv.scrollView.showsVerticalScrollIndicator = false
wv.scrollView.showsHorizontalScrollIndicator = false
return wv
}()
override func viewDidLoad() {
super.viewDidLoad()
webView.frame = view.bounds
view.addSubview(webView)
observerAndUpdateWebViewHeight()
}
// 监听网页滚动区域变化
private func observerAndUpdateWebViewHeight() {
observation = webView.scrollView.observe(\UIScrollView.contentSize, options: [.new]) { [weak self] (_, change) in
guard let self = self else { return }
// 直接获取新值
let webH = change.newValue?.height ?? 0
self.webView.frame.size.height = webH
}
}
}
相较原来OC
的处理方式, Swift 优势:
- 原来的监听KeyPath使用的是字符串,有可能造成人为的错误
- 设定观察和处理观察代码放在一起,代码维护难度降低;
- 不需要使用context来区分是哪个观察量发生变化;
- 处理时得到的是类型安全的结果,不是在字典中取值;
- observation被观察者持有,生命周期随着观察者的释放而结束,不像原来还需要寻找时机移除观察者
注意:
- 在
Swift
中使用,有一些限制,如果相对我们自定义的类进行属性监听的话, 需要对属性使用dynamic
和@objc
进行修饰.
class MyClass: NSObject {
dynamic var phone: String = ""
@objc var name: String = ""
}
网友评论