一开始我想知道为什么如果我们子类化UIView
,并且我们实现了一个drawRect
要调用的方法,但同时,如果我们在这个视图中添加按钮或标签,并调整它们的位置坐标,它们也会被重新绘制...... ..所以这个视图似乎有两种绘制机制,一种用于自身,另一种用于此视图中的对象。
但事实证明,似乎每 1/60 秒,整棵树就被遍历一遍。从顶视图对象开始,iOS 会访问所有的子对象,然后调用drawRect
,self
子对象也以同样的方式被访问,孙子对象被访问,并且drawRect
为每个第一级子对象调用,如下所示:
-(void) processViewObject:(UIView *) obj {
// pseudo code:
foreach children "c" already sorted by zOrder from most negative to -1
processViewObject(c) // recursion
if ([self needsUpdateOrNot] == YES)
[self drawRect]
foreach children "c" already sorted by zOrder from 1 to the greatest number
processViewObject(c) // recursion
}
并且每 1/60 秒拨打一次电话,对于
processViewObject(topViewObject); // start from the topmost view object
这样任何视图都可以在drawRect
和视图的子视图中绘制自己,如果它们的任何位置坐标被修改,或者如果它们的内容发生变化,那么脏位needsUpdateOrNot
已经设置得更早,因此drawRect
将调用它们来重新绘制自己。
或者实际上,如果设置了视图的脏位,那么可能该位将在递归中传递给子项,如下所示:
foreach children "c" already sorted by zOrder from 1 to the greatest number
processViewObject(c, [self needsUpdateOrNot])
这样如果设置了父级的脏位,那么子级也需要重新绘制,以便正确绘制该视图内的整个图片。
此外,每个漂亮的按钮或标签都只是一个UIView
对象,drawRect
已经实现了一个可以绘制漂亮图像的对象——按钮、复选框、标签或任何其他小部件。
这就是一切如何在屏幕上绘制的整体机制?我听说过“从不调用drawRect
自己,而是让它被调用”,但从来没有完全理解为什么,但如果以上是整体机制,那么看起来就是这个原因。
我想知道这是否与Microsoft Windows或任何GUI操作系统上实际上几乎相同的机制相同,并且在某些游戏框架上,我认为无论是否设置了脏位,都会绘制所有内容,因为据说,事情在游戏中一直在移动,无论如何,框架只是每 1/60 秒绘制一次。
上面的zOrder
处理顺序是在某个框架的代码中,所以先绘制所有负zOrder子项,然后self
绘制,再绘制所有正zOrder子项。(这就是 zOrder 是如何以 Painter Model 的方式在屏幕上绘制事物的方式实现的——后者绘制的将掩盖之前绘制的。)如果相对于子项的 zOrder 也是如此——zOrder 的self
数量如果它是相对于它自己的兄弟姐妹,而不是相对于它的孩子。0
self
以上准确吗?如果给出答案,如果可能的话,是否可以引用部分源代码或参考,以便我们知道它是如何工作的标准或官方方式?