18

我找不到一个像样的答案来解释这两个功能之间的区别。每个人什么时候被叫到,一个人与另一个人有何不同?

例如,我不能只在 drawrect 中布局我的视图吗?

谢谢

4

2 回答 2

59

-layoutSubviews-layoutIfNeeded如果设置了“需要布局”标志(使用-setNeedsLayout, 或在视图边界更改时自动),则调用。用它来定位你的视图[编辑:用它来定位子视图]。

-drawRect:-displayIfNeeded如果设置了“显示需要”标志(使用-setNeedsDisplay,或者如果您设置了 ,则自动调用view.contentMode = UIViewContentModeRedraw)。

两者都由 UIKit/CoreAnimation 在绘制到屏幕之前自动调用-layoutIfNeeded-displayIfNeeded你很少需要直接打电话给他们。

你可以定位你的子视图-drawRect:(你甚至可以添加子视图!),但这是不明智的:

  • 默认情况下,-setNeedsDisplay不会在边界更改时自动调用。
  • 实现-drawRect:会降低性能(UIKit/CoreAnimation 必须为您创建一个位图支持的图形上下文);仅当您需要执行自定义绘图时才这样做。
  • 您需要在 中重绘视图-drawRect:。画画很贵。移动视图很便宜。
  • UIKit/CoreAnimation 可能会先进行布局传递,然后再进行绘图传递。CoreAnimation 可以使用布局信息来决定需要绘制哪些视图(例如,它可以忽略被不透明子视图、屏幕外视图或 clipsToBounds=YES 视图边界之外的子视图遮挡的视图;或者它只能绘制大视图)。如果在绘制过程中移动视图,CoreAnimation 可能无法正确绘制它们。

编辑:当我醒着时还有更多细节:

“显示”和“绘制”有什么区别?显示由-[CALayer display]; 默认实现是(大约)

  • 如果层的委托响应-displayLayer:,调用 [self.delegate displayLayer:self]-displayLayer:应该设置layer.content为(例如)一个CGImage,
  • 否则,如果该层的委托响应-drawLayer:inContext:,设置一个位图支持的上下文,调用[self.delegate drawLayer:self inContext:context],并将输出保存到layer.content(输出实际上是一个 CABackingStore,大概是一个私有 API)
  • 否则,不要更改layer.content

视图是层的委托,所以你可以实现-[MyView displayLayer:],并做一些有趣的事情,比如

  • self.layer.contents = (id)([UIImage imageNamed:@"foo"].CGImage)(这大致是 UIImageView 所做的)
  • 无操作,以防止任何“绘图”。如果您将 UIToolbar 等子类化并希望给它一个透明背景,这可能会很有用。(这也阻止了 CGContext/CABackingStore 的创建。)
  • 在没有性能损失的情况下移动子视图(但由于上述原因,这仍然不是一个好主意)。
于 2010-09-25T01:17:31.850 回答
-2

也许我没有所有的答案,但我可以说: - layoutSubviews 在视图框架发生变化时被调用 - drawRect 在 setNeedDisplay 被调用时被调用

大多数时候你不会使用 layoutSubviews。

可能还有其他情况,但它可以给你第一个答案^^

祝你好运

于 2010-09-24T20:13:24.853 回答