代码之家  ›  专栏  ›  技术社区  ›  HuaTham

uiview边界和帧的属性观察器反应不同

  •  1
  • HuaTham  · 技术社区  · 6 年前
    public weak var boundsDelegate:viewboundsObservation?
    
    意志力{
    边界委托?.boundswillchange(自我)
    迪塞特{
    }
    
    意志力{
    print(“frame willset frame:\(frame),bounds:\(bounds)”)
    边界委托?.boundswillchange(自我)
    }
    迪塞特{
    print(“frame didset frame:\(frame),bounds:\(bounds)”)
    边界委托?.boundsdidchange(自我)
    }
    }
    }
    

    在我的示例代码中,如果旋转设备,您将看到在一种情况下,当我观察根视图时(viewcontrollersself.view——以蓝色显示),我将永远不会收到关于boundschange的通知,尽管它实际发生了更改。与此相反的是子视图——我从未收到关于framechange的通知,尽管它已经更改了。

    我正在Xcode9.3上测试这个项目,iOS11.4sdk用于iPad Air和iPad Pro等设备。我还没有尝试过使用iOS 12测试版。

      here)我遇到了一个非常奇怪的差异:didSetwillSet将根据放置位置不同触发

      • ,我只会得到事件来自变化。
      • 子视图迪塞特事件来自变化。

      hereviewDidLayoutSubviews()提到heredoc)。意志力视图边界框架

      this question但它只涉及初始化阶段,也没有提到观察子视图的情况。

      要看到这一点,请查看¨my sample project

      观察者也一样,甚至有时不召集观察员。最后,我找到了它们工作方式不同的关键设置:视图在视图层次结构中的位置,如上所述。

      框架边界

      这是我的

          public weak var boundsDelegate: ViewBoundsObserving?
      
          public override var bounds: CGRect {
              willSet {
                  print("BOUNDS willSet bounds: \(bounds), frame: \(frame)")
                  boundsDelegate?.boundsWillChange(self)
              }
              didSet {
                  print("BOUNDS didSet bounds: \(bounds), frame: \(frame)")
                  boundsDelegate?.boundsDidChange(self)
              }
          }
      
          public override var frame: CGRect {
              willSet {
                  print("FRAME willSet frame: \(frame), bounds: \(bounds)")
                  boundsDelegate?.boundsWillChange(self)
              }
              didSet {
                  print("FRAME didSet frame: \(frame), bounds: \(bounds)")
                  boundsDelegate?.boundsDidChange(self)
              }
          }
      }
      

      在我的示例代码中,如果旋转设备,在我观察根视图的情况下,您将看到(ViewControllerself.view--蓝色),我永远不会得到通知改变,尽管它实际上已经改变了。与之相反的是一个子视图——我从来没有得到过通知改变,尽管改变了。

      enter image description here enter image description here enter image description here

      我正在Xcode9.3上测试这个项目,iOS11.4sdk用于iPad Air和iPad Pro等设备。我还没有尝试过iOS 12测试版。

      • 迪塞特意志力视图
      • 对于迪塞特是否也触发(对于子视图)?反之亦然(对于根视图)?
      • 如果有的话,有什么方法可以确保我可以随时观察A的变化
    1 回复  |  直到 6 年前
        1
  •  0
  •   HuaTham    6 年前

    Apple Developer Forum QuinceyMorris

    ……willset/didset访问器只有在更改通过其自身属性时才会触发。您无法预测或假设将使用哪个属性。即使你现在看到了规律性,也可能会有不同的边缘情况,并且未来的行为可能会改变。

    layoutSubviews ,这是我更新的子类(就像 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()
        }
    }