Jer*_*y L 3 core-animation calayer uiview drawrect ios
我真的不知道如何的CALayer的display,并drawInContext涉及到drawRect在视图中.
如果我有一个NSTimer设置[self.view setNeedsDisplay]每1秒,则drawRect每1秒调用一次,如内部的NSLog语句所示drawRect.
但是如果我将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];
}
Run Code Online (Sandbox Code Playgroud)
所以,比方说,如果在视图中的位置(100,100)有月亮(由Core Graphics绘制的圆圈),现在我将其更改为位置(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逻辑指示重绘(它也可以在那里使用随机数作为坐标).其他类型的脏是它被掩盖或消失,现在需要重新显示.
rob*_*off 12
当需要显示某个层并且没有有效的后备存储(可能是因为该层接收到setNeedsDisplay消息)时,系统会将该display消息发送到该层.
该-[CALayer display]方法看起来大致如下:
- (void)display {
if ([self.delegate respondsToSelector:@selector(displayLayer:)]) {
[[self.delegate retain] displayLayer:self];
[self.delegate release];
return;
}
CABackingStoreRef backing = _backingStore;
if (!backing) {
backing = _backingStore = ... code here to create and configure
the CABackingStore properly, given the layer size, isOpaque,
contentScale, etc.
}
CGContextRef gc = ... code here to create a CGContext that draws into backing,
with the proper clip region
... also code to set up a bitmap in memory shared with the WindowServer process
[self drawInContext:gc];
self.contents = backing;
}
Run Code Online (Sandbox Code Playgroud)
所以,如果你覆盖display,除非你打电话,否则不会发生这种情况[super display].如果你执行displayLayer:的FooView,你必须创建自己CGImage莫名其妙并将其存储在图层的contents属性.
该-[CALayer drawInContext:]方法看起来大致如下:
- (void)drawInContext:(CGContextRef)gc {
if ([self.delegate respondsToSelector:@selector(drawLayer:inContext:)]) {
[[self.delegate retain] drawLayer:self inContext:gc];
[self.delegate release];
return;
} else {
CAAction *action = [self actionForKey:@"onDraw"];
if (action) {
NSDictionary *args = [NSDictionary dictionaryWithObject:gc forKey:@"context"];
[action runActionForKey:@"onDraw" object:self arguments:args];
}
}
}
Run Code Online (Sandbox Code Playgroud)
onDraw据我所知,该行动未记录在案.
该-[UIView drawLayer:inContext:]方法看起来大致如下:
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)gc {
set gc's stroke and fill color spaces to device RGB;
UIGraphicsPushContext(gc);
fill gc with the view's background color;
if ([self respondsToSelector:@selector(drawRect:)]) {
[self drawRect:CGContextGetClipBoundingBox(gc)];
}
UIGraphicsPopContext(gc);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5712 次 |
| 最近记录: |