一开始我想知道为什么我们要继承UIView ,我们实现了一个 drawRect要调用的方法,但同时,如果我们向该 View 添加按钮或标签,并调整它们的位置坐标,它们也会被重新绘制……所以似乎有两种绘制机制此 View ,一个用于自身,一个用于此 View 中的对象。
但事实证明,似乎每隔 1/60 秒,整棵树就被遍历了一遍。从顶 View 对象开始,iOS 会访问所有的 child ,然后调用 drawRect对于 self , children 也以同样的方式被访问,孙子被访问,并且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
这样任何 View 都可以在 drawRect 中绘制自己, 和 View 的 child ,如果他们的任何位置坐标被修改,或者如果他们的内容被改变,那么脏位 needsUpdateOrNot之前已经设置好了,所以他们的drawRect将被调用重新绘制自己。
或者实际上,如果设置了 View 的脏位,那么这个位可能会在递归中传递给子级,如下所示:
foreach children "c" already sorted by zOrder from 1 to the greatest number
processViewObject(c, [self needsUpdateOrNot])
因此,如果设置了父级的脏位,则子级也需要重绘,才能正确绘制此 View 中的整个画面。
此外,每个漂亮的按钮或标签都只是一个 UIView对象,带有 drawRect已经实现,可以绘制出漂亮的图片来表示它是什么——一个按钮、一个复选框、一个标签或任何其他小部件。
这就是在屏幕上绘制所有内容的整体机制吗?我听说过“永远不要自己调用 drawRect,而是让它被调用”,但从未完全理解为什么,但如果以上是整体机制,那么看起来就是原因。
我想知道这是否是与 Microsoft Windows 或任何 GUI 操作系统实际上几乎相同的机制,并且在某些游戏框架上,我认为无论是否设置脏位,所有内容都会被绘制,因为据推测,游戏中的东西一直在移动,而框架只是每 1/60 秒绘制一次所有的东西。
zOrder上面的处理顺序是在某些框架的代码中,因此首先绘制所有负 zOrder 子项,然后绘制 self绘制,然后绘制所有正 zOrder 子项。 (这就是 zOrder 是如何以 Painter 模型在屏幕上绘制事物的方式实现的——后绘制的会覆盖早绘制的。)所以 self是 0 的 zOrder如果相对于子项——self 的 zOrder 编号如果它是相对于它自己的 sibling ,而不是相对于它的 child ,那么这很重要。
以上说法准确吗?如果给出答案,如果可能的话,能否引用部分源代码或引用文献,以便我们知道这是标准的或官方的工作方式?
最佳答案
我认为您将合成与绘图混淆了。这两者是不同的概念,它们在不同的时间点发挥作用。
在 iOS 上,每个 UIView 都由一个 CALayer 支持,它实际上是一个围绕矩形 OpenGL ES 纹理的轻量级包装器。当一个 UIView 需要完全重绘时(第一次出现,或者通过不同情况强制重绘),-drawRect:被触发并使用 Core Graphics 将矢量图形渲染成位图。然后该位图通过 CALayer 上传到 GPU 并存储在那里。
当需要移动 View 或对其应用简单的变换(旋转、缩放等)时,它不会重新绘制,只是移动背衬层并合成可见场景中的层。同样,每个 View 和 subview 都有自己的支持层,因此它们在 View (层)层次结构中按 Z 顺序组合。在 GPU 上合成是一项非常快的操作,比最初绘制 View 快得多。这就是在 iOS 中实现平滑滚动或动画的原因,因为这些底层矩形图像只是在 GPU 上四处移动并合成。这也是为什么在 View 和图层中具有透明度会减慢滚动等操作的原因,因为合成非不透明图层比不透明图层慢得多。
当您移动 subview 或位于它们上方的其他 View 时,不会重绘 View 的重叠部分,因为合成会处理可见和不可见的部分。唯一一次实际 -drawRect:重绘发生在您使用 -setNeedsDisplay 时强制重新渲染或者如果您设置 needsDisplayOnBoundsChange为 CALayer 重绘自身以响应大小或形状的变化。
我认为 jturton 链接到的部分文档在涉及 iOS 或 Mac 上的图层支持 View 时是不正确的。它似乎是在 Mac 缺少 Core Animation 时编写的,并且是呈现非图层支持的 NSView 的方式,因此它可能是从旧引用中复制和粘贴的。这不是 layer-backed views 的情况,它们在部分遮挡时不会重绘自己。您可以通过在 -drawRect: 时记录来自己测试在层支持的 UIView 中调用,您会看到当 View 只是在彼此之上移动时它不会被触发。
关于ios - 在 iOS 上,在屏幕上绘制任何内容的总体机制是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10644014/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象