我不太理解CALayer的display和drawInContext如何与视图中的drawRect相关。
如果我有一个NSTimer,每1秒钟设置一次[self.view setNeedsDisplay],那么drawRect将每1秒钟被调用一次,这可以通过在drawRect内部使用NSLog语句来显示。
但是,如果我子类化一个CALayer并将其用于视图,则如果我使display方法为空,则现在drawRect将永远不会被调用。更新:但是display每1秒钟被调用一次,这可以通过NSLog语句来显示。
如果我删除该空的display方法并添加一个空的drawInContext方法,则再次不会调用drawRect。更新:但是,drawInContext每1秒钟被调用一次,这可以通过NSLog语句来显示。
到底发生了什么?看起来display可以有选择地调用drawInContext,而drawInContext可以以某种方式有选择地调用drawRect(如何实现?),但是真正的情况是什么?
更新:有更多关于答案的线索:
我将CoolLayer.m代码更改为以下内容:
假设视图中有一个由Core Graphics绘制的圆形(作为月亮)位于(100,100)位置,现在我将其更改为(200,200)位置,自然地,我会调用
即使如此,入口点仍然是CALayer的
所以我们可以看到,CoolLayer的
最后,CALayer的
所以我猜测两个问题:即使没有图像缓存,为什么它还要进入CALayer?因为通过这种机制,在上下文中绘制图像,最后返回到
我还不太确定的另一件事是:如果
如果我有一个NSTimer,每1秒钟设置一次[self.view setNeedsDisplay],那么drawRect将每1秒钟被调用一次,这可以通过在drawRect内部使用NSLog语句来显示。
但是,如果我子类化一个CALayer并将其用于视图,则如果我使display方法为空,则现在drawRect将永远不会被调用。更新:但是display每1秒钟被调用一次,这可以通过NSLog语句来显示。
如果我删除该空的display方法并添加一个空的drawInContext方法,则再次不会调用drawRect。更新:但是,drawInContext每1秒钟被调用一次,这可以通过NSLog语句来显示。
到底发生了什么?看起来display可以有选择地调用drawInContext,而drawInContext可以以某种方式有选择地调用drawRect(如何实现?),但是真正的情况是什么?
更新:有更多关于答案的线索:
我将CoolLayer.m代码更改为以下内容:
-(void) display {
NSLog(@"In CoolLayer's display method");
[super display];
}
-(void) drawInContext:(CGContextRef)ctx {
NSLog(@"In CoolLayer's drawInContext method");
[super drawInContext:ctx];
}
假设视图中有一个由Core Graphics绘制的圆形(作为月亮)位于(100,100)位置,现在我将其更改为(200,200)位置,自然地,我会调用
[self.view setNeedsDisplay]
,现在,CALayer将没有任何缓存用于新的视图图像,因为我的drawRect
规定了月亮应该如何显示。即使如此,入口点仍然是CALayer的
display
,然后是CALayer的drawInContext
:如果我在drawRect
设置断点,则调用堆栈显示:所以我们可以看到,CoolLayer的
display
首先被调用,然后进入CALayer的display
,然后是CoolLayer的drawInContext
,然后是CALayer的drawInContext
,即使在这种情况下,新图像没有任何这样的缓存存在。最后,CALayer的
drawInContext
调用代理的drawLayer:InContext
。 代理是视图(FooView或UIView)... drawLayer:InContext
是UIView中的默认实现(因为我没有覆盖它)。 最终,drawLayer:InContext
调用drawRect
。所以我猜测两个问题:即使没有图像缓存,为什么它还要进入CALayer?因为通过这种机制,在上下文中绘制图像,最后返回到
display
,并从此上下文创建CGImage,然后将其设置为新的缓存图像。这就是CALayer缓存图像的方式。我还不太确定的另一件事是:如果
[self.view setNeedsDisplay]
总是触发调用drawRect
,那么何时可以使用CALayer中的缓存图像呢?可能是在Mac OS X上,当另一个窗口覆盖窗口时,现在顶部窗口被移开。现在我们不需要调用drawRect
重新绘制所有内容,而是可以使用CALayer中的缓存图像。或者在iOS上,如果我们停止应用程序,做其他事情,然后回到应用程序,则可以使用缓存的图像,而不是调用drawRect
。但是如何区分这两种“脏”状态呢?一个是“未知脏”--需要根据drawRect
逻辑重新绘制月亮(也可以在那里使用随机数进行坐标)。另一种脏状态是它被覆盖或消失了,现在需要重新显示。