简体   繁体   English

禁用/启用按钮时,视图如何重绘?

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

If I enable/disable a button…what method would get called on the view? 如果启用/禁用按钮,视图上将调用哪种方法?

I've already placed a breakpoint on the layoutSubviews and don't see it reaching there. 我已经在layoutSubviews上放置了一个断点,但看不到它到达那里。 Nor it reaches us to the viewController's viewWillLayoutSubviews . 它也没有到达viewController的viewWillLayoutSubviews So I'm just curious to know how it works and what method it triggers 所以我很好奇它的工作原理和触发的方法

That's a good question. 这是个好问题。 I got curious about this myself, so I created a simple UIButton subclass and put breakpoints on a few overridden methods. 我自己对此感到很好奇,因此我创建了一个简单的UIButton子类,并在一些重写的​​方法上设置了断点。 Here are my findings: 这是我的发现:

  1. Called setEnabled: on a UIButton subclass instance which I called MyButton in viewDidLoad UIButton子类实例上调用setEnabled: UIButton我在viewDidLoad中将其称为MyButton
  2. This triggered a call to setNeedsDisplay method. 这触发了对setNeedsDisplay方法的调用。 It was called internally by the setEnabled method of the UIButton class. 它是由UIButton类的setEnabled方法在内部调用的。 As you can see from the stack trace in this screenshot: 从该屏幕快照的堆栈跟踪中可以看到:

    在此处输入图片说明

  3. After setNeedsDisplay , the setNeedsLayout method was triggered. setNeedsDisplay之后,将触发setNeedsLayout方法。 The stack trace was similar to the earlier call: 堆栈跟踪类似于先前的调用:

    在此处输入图片说明

  4. After this the following methods were called in this order: layoutSubviews , drawLayer:inContext: , drawRect: 之后, drawLayer:inContext:以下顺序调用以下方法: layoutSubviewsdrawLayer:inContext:drawRect:

According to Apple's documentation of the UIView class, 根据Apple的 UIView文档

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. 您可以通过调用视图的setNeedsDisplay()或setNeedsDisplay(_ :)方法来实现。 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. 因为它要等到下一个绘图周期才能更新视图,所以您可以在多个视图上调用这些方法以同时更新它们。

And here is the documentation on the enabled boolean of UIControl : 这是关于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. 将此属性的值设置为YES可启用控件,而将NO禁用即可。 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; 将此属性设置为NO会将UIControlStateDisabled标志添加到控件的状态位掩码中。 enabling the control again removes that flag. 再次启用控件将删除该标志。

They mention that a disabled control may re-draw itself differently. 他们提到禁用的控件可能会以不同的方式重绘自身。 They also mention the control's state bitmask is updated. 他们还提到控件的state位掩码已更新。 So, I believe, internally Apple's UIButton class calls the setNeedsDisplay method, which in-turn forces to re-draw itself. 因此,我相信,Apple的UIButton类在内部调用setNeedsDisplay方法,从而强制重新绘制自身。 Based on the (UIControlState) state property, the button draws itself respectively. 基于(UIControlState) state属性,按钮分别进行绘制。 You can find more on UIButton drawing here (look at Table 2 Appearance attributes) and UIView drawing here . 您可以在此处找到有关UIButton绘图的更多信息(请参见表2的外观属性) ,并在此处找到 UIView绘图的更多信息

But it probably won't trigger any events on the UIViewController 's view which has the button as a subview. 但是它可能不会在以按钮为子视图的UIViewController的视图上触发任何事件。 Although, you could use KVO and observe the enabled property if you want to listen to changes to the property in your view controller or in the button's superview. 但是,如果您想在视图控制器或按钮的超级视图中侦听对该属性的更改,则可以使用KVO并观察已enabled属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM