由于 autoresizingmask 导致视图调整大小时,KVO 不适用于 `UIView.bounds` 键路径
KVO not working for `UIView.bounds` keypath when view resizing happens due to `autoresizingmask`
我有以下视图控制器:
class ViewController: UIViewController {
lazy var superView: UIView = {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
view.backgroundColor = UIColor.white
return view
}()
lazy var childView: UIView = {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.backgroundColor = UIColor.black
return view
}()
var boundObservation: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.orange
self.view.addSubview(self.superView)
self.superView.center = CGPoint(
x: self.view.frame.width / 2.0,
y: self.view.frame.height / 2.0
)
self.superView.addSubview(self.childView)
self.childView.center = CGPoint(
x: self.superView.frame.width / 2.0,
y: self.superView.frame.height / 2.0
)
self.childView.autoresizingMask = .flexibleWidth
let button = UIButton(type: .system)
button.setTitle("Tap me!", for: .normal)
button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
self.view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
button.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: -24).isActive = true
self.boundObservation = self.childView.observe(
\UIView.bounds,
options: .new,
changeHandler: { view, change in
print(change.newValue ?? "nil")
})
}
@objc func buttonTapped(_ sender: UIButton) {
let view = self.superView
let previousSize = view.bounds.size
view.bounds.size = CGSize(width: previousSize.width + 50, height: previousSize.height + 20)
}
}
我的 childView
get 在 superView
调整大小时由于自动调整大小掩码而自动调整大小。但是 KVO 观察没有被调用。为什么 KVO 在这种情况下不起作用?
你可以这样做
private var observer: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
observer = view.observe(\.bounds) { object, _ in
print(object.bounds)
}
// ...
}
override func viewWillDisappear(_ animated: Bool) {
observer?.invalidate()
//...
}
我的问题是通过观察 \.layer.bounds
而不是 \UIView.bounds
解决的,因为我了解到图层是视图布局的“真实来源”,所以我怀疑自动调整大小掩码正在直接修改图层边界不经过 UIView.bounds
我有以下视图控制器:
class ViewController: UIViewController {
lazy var superView: UIView = {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
view.backgroundColor = UIColor.white
return view
}()
lazy var childView: UIView = {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.backgroundColor = UIColor.black
return view
}()
var boundObservation: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.orange
self.view.addSubview(self.superView)
self.superView.center = CGPoint(
x: self.view.frame.width / 2.0,
y: self.view.frame.height / 2.0
)
self.superView.addSubview(self.childView)
self.childView.center = CGPoint(
x: self.superView.frame.width / 2.0,
y: self.superView.frame.height / 2.0
)
self.childView.autoresizingMask = .flexibleWidth
let button = UIButton(type: .system)
button.setTitle("Tap me!", for: .normal)
button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
self.view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
button.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: -24).isActive = true
self.boundObservation = self.childView.observe(
\UIView.bounds,
options: .new,
changeHandler: { view, change in
print(change.newValue ?? "nil")
})
}
@objc func buttonTapped(_ sender: UIButton) {
let view = self.superView
let previousSize = view.bounds.size
view.bounds.size = CGSize(width: previousSize.width + 50, height: previousSize.height + 20)
}
}
我的 childView
get 在 superView
调整大小时由于自动调整大小掩码而自动调整大小。但是 KVO 观察没有被调用。为什么 KVO 在这种情况下不起作用?
你可以这样做
private var observer: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
observer = view.observe(\.bounds) { object, _ in
print(object.bounds)
}
// ...
}
override func viewWillDisappear(_ animated: Bool) {
observer?.invalidate()
//...
}
我的问题是通过观察 \.layer.bounds
而不是 \UIView.bounds
解决的,因为我了解到图层是视图布局的“真实来源”,所以我怀疑自动调整大小掩码正在直接修改图层边界不经过 UIView.bounds