当我 disable/enable 一个按钮时,视图如何重绘自己?

How does the view redraw itself when I disable/enable a button?

如果我 enable/disable 一个按钮…视图上会调用什么方法?

我已经在 layoutSubviews 上放置了一个断点,但没有看到它到达那里。它也没有到达 viewController 的 viewWillLayoutSubviews。所以我只是想知道它是如何工作的以及它触发什么方法

这是个好问题。我自己对此很好奇,所以我创建了一个简单的 UIButton subclass 并在一些重写的​​方法上放置了断点。这是我的发现:

  1. UIButton 子 class 实例上调用了 setEnabled:,我在 viewDidLoad
  2. 中调用了 MyButton
  3. 这触发了对 setNeedsDisplay 方法的调用。它由 UIButton class 的 setEnabled 方法在内部调用。从此屏幕截图中的堆栈跟踪可以看出:

  4. setNeedsDisplay后,触发了setNeedsLayout方法。堆栈跟踪类似于之前的调用:

  5. 此后按顺序调用了以下方法:layoutSubviewsdrawLayer:inContext:drawRect:

根据 Apple's documentationUIView class,

When the actual content of your view changes, it is your responsibility to notify the system that your view needs to be redrawn. You do this by calling your view’s setNeedsDisplay() or setNeedsDisplay(_:) method of the view. These methods let the system know that it should update the view during the next drawing cycle. Because it waits until the next drawing cycle to update the view, you can call these methods on multiple views to update them at the same time.

这是关于 UIControlenabled 布尔值的文档:

A Boolean value indicating whether the control is enabled. Set the value of this property to YES to enable the control or NO to disable it. An enabled control is capable of responding to user interactions, whereas a disabled control ignores touch events and may draw itself differently. Setting this property to NO adds the UIControlStateDisabled flag to the control’s state bitmask; enabling the control again removes that flag.

他们提到禁用的控件可能会以不同的方式重新绘制自身。他们还提到控件的 state 位掩码已更新。因此,我相信,Apple 的 UIButton class 内部会调用 setNeedsDisplay 方法,该方法反过来会强制重新绘制自身。基于(UIControlState) state 属性,按钮分别绘制自己。您可以在 此处找到有关 UIButton 绘图的更多信息(查看 Table 2 外观属性)和UIView绘图here.

但它可能不会在 UIViewController 的视图上触发任何事件,该视图将按钮作为子视图。虽然,如果您想在视图控制器或按钮的超级视图中收听对 属性 的更改,则可以使用 KVO 并观察 enabled 属性。