【发布时间】:2018-04-23 15:25:48
【问题描述】:
如果我启用/禁用按钮……视图会调用什么方法?
我已经在layoutSubviews 上放置了一个断点,但没有看到它到达那里。也不会到达 viewController 的 viewWillLayoutSubviews。所以我只是想知道它是如何工作的以及它触发了什么方法
【问题讨论】:
标签: ios uiview autolayout drawing layoutsubviews
如果我启用/禁用按钮……视图会调用什么方法?
我已经在layoutSubviews 上放置了一个断点,但没有看到它到达那里。也不会到达 viewController 的 viewWillLayoutSubviews。所以我只是想知道它是如何工作的以及它触发了什么方法
【问题讨论】:
标签: ios uiview autolayout drawing layoutsubviews
这是个好问题。我自己对此很好奇,所以我创建了一个简单的UIButton 子类,并在一些被覆盖的方法上设置了断点。以下是我的发现:
UIButton 子类实例上调用setEnabled:,我在viewDidLoad 中调用MyButton
这触发了对setNeedsDisplay 方法的调用。它由UIButton 类的setEnabled 方法在内部调用。正如您在此屏幕截图中的堆栈跟踪中看到的那样:
在setNeedsDisplay之后,触发了setNeedsLayout方法。堆栈跟踪与之前的调用类似:
之后依次调用以下方法:layoutSubviews、drawLayer:inContext:、drawRect:
根据UIView类的Apple's documentation,
当您的视图的实际内容发生变化时,您有责任通知系统您的视图需要重新绘制。为此,您可以调用视图的 setNeedsDisplay() 或 setNeedsDisplay(_:) 方法。这些方法让系统知道它应该在下一个绘图周期更新视图。因为它要等到下一个绘制周期才更新视图,所以可以在多个视图上调用这些方法同时更新它们。
这里是关于UIControl 的enabled 布尔值的文档:
一个布尔值,指示控件是否启用。 将此属性的值设置为 YES 以启用控件或设置为 NO 以禁用它。启用的控件能够响应用户交互,而禁用的控件会忽略触摸事件并可能以不同的方式绘制自身。将此属性设置为 NO 会将 UIControlStateDisabled 标志添加到控件的状态位掩码;再次启用控件会删除该标志。
他们提到禁用的控件可能会以不同的方式重新绘制自己。他们还提到控件的state 位掩码已更新。所以,我相信,Apple 的内部UIButton 类调用setNeedsDisplay 方法,这反过来又强制重新绘制自己。基于(UIControlState) state 属性,按钮分别绘制自身。您可以在 UIButton 绘图here (look at Table 2
Appearance attributes) 和 UIView 绘图here 上找到更多信息。
但它可能不会在UIViewController 的视图上触发任何事件,该视图将按钮作为子视图。不过,如果您想在视图控制器或按钮的超级视图中监听属性的更改,您可以使用 KVO 并观察 enabled 属性。
【讨论】:
UIButton 层?我实际上是在按钮的父视图和视图的父视图上写的。我没有覆盖按钮本身的任何方法。我想这就是全部。 2. 只是为了确定。你是说没有方法冒泡到按钮的超级视图?!