Property observers for UIView bounds and frame react differently

后端 未结 1 1401
刺人心
刺人心 2021-01-06 12:51

While I am exploring the option to observe a UIView\'s bounds or frame change (mentioned here and here), I have encountered a very str

相关标签:
1条回答
  • 2021-01-06 13:23

    From my repost in Apple Developer Forum, QuinceyMorris helped me clarifying issues with this approach as well as an approach that would work no matter where I put the view in the view hierarchy.

    ... an Obj-C property can change value without having its setter called. Changing the instance variable (of simple properties) is a very common Obj-C pattern. It is of course not KVO compliant without additional work, but that's why KVO compliance is not found universally.

    ... Your willSet/didSet accessors will only trigger when the change goes through their own property. There is nothing you can predict or assume about which property will be used. Even if you see a regularity now, there may be edge cases that are different, and the behavior may change in the future.

    Based on his recommendation that I override layoutSubviews, here's my updated subclass (just like this answer):

    public protocol ViewBoundsObserving: class {
        // Notifies the delegate that view's `bounds` has changed.
        // Use `view.bounds` to access current bounds
        func boundsDidChange(_ view: BoundsObservableView, from previousBounds: CGRect);
    }
    
    /// You can observe bounds change with this view subclass via `ViewBoundsObserving` delegate.
    public class BoundsObservableView: UIView {
        
        public weak var boundsDelegate: ViewBoundsObserving?
        
        private var previousBounds: CGRect = .zero
        
        public override func layoutSubviews() {
            if (bounds != previousBounds) {
                print("Bounds changed from \(previousBounds) to \(bounds)")
                boundsDelegate?.boundsDidChange(self, from: previousBounds)
                previousBounds = bounds
            }
            
            // UIView's implementation will layout subviews for me using Auto Resizing mask or Auto Layout constraints.
            super.layoutSubviews()
        }
    }
    
    0 讨论(0)
提交回复
热议问题