【问题标题】:Not all tiles redrawn after CATiledLayer -setNeedsDisplay在 CATiledLayer -setNeedsDisplay 之后并非所有图块都重绘
【发布时间】:2011-07-09 01:29:58
【问题描述】:

我的视图有一个CATiledLayer。视图控制器具有自定义缩放行为,因此-scrollViewDidEndZooming 每个图块都需要重绘。但是,即使每次缩放后都会在图层上调用-setNeedsDisplay,但并非所有图块都被重绘。这导致视图有时在缩放后看起来不正确。 (应该只出现在 1 个图块中的东西出现在多个地方)。它通常会在另一次缩放后自行纠正。

这是相关代码。 updatedRects 用于测试——它存储了-drawLayer 请求绘制的唯一矩形。

CanvasView.h:

@interface CanvasView : UIView
@property (nonatomic, retain) NSMutableSet *updatedRects; 
@end

CanvasView.m:

@implementation CanvasView

@synthesize updatedRects; 

+ (Class)layerClass 
{
    return [CATiledLayer class];
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    CGRect rect = CGContextGetClipBoundingBox(context); 
    [updatedRects addObject:[NSValue valueWithCGRect:rect]]; 

    CGContextSaveGState(context); 
    CGContextTranslateCTM(context, rect.origin.x, rect.origin.y); 
    // ...draw into context...
    CGContextRestoreGState(context); 
}

@end

MyViewController.m:

@implementation MyViewController

- (void)viewDidLoad 
{
    [super viewDidLoad];

    canvasView.updatedRects = [NSMutableSet set]; 
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
    canvasView.transform = CGAffineTransformIdentity; 
    canvasView.frame = CGRectMake(0, 0, canvasView.frame.size.width * scale, canvasView.frame.size.height); 
    [self updateCanvas]; 
}

- (void)updateCanvas
{
    NSLog(@"# rects updated: %d", [canvasView.updatedRects count]); 
    [canvasView.updatedRects removeAllObjects]; 
    canvasView.frame = CGRectMake(canvasView.frame.origin.x, canvasView.frame.origin.y, canvasView.frame.size.width, myHeight); 
    CGFloat tileSize = 256; 
    NSLog(@"next # rects updated will be: %f", [canvasView.layer bounds].size.width / tileSize); 
    [canvasView.layer setNeedsDisplay]; 
}

@end

在进行测试时,我总是在缩放后一直滚动到整个视图,以确保看到每个图块。每当视图看起来错误时,预测的“下一个更新的矩形数”大于下一次调用-updateCanvas 时的实际“更新的矩形数”。什么会导致这个?

编辑:

这是一种可视化问题的更好方法。每次调用updateCanvas,我都会让它改变绘制瓷砖的背景颜色并记录它被调用的时间——颜色和时间存储在canvasView中。在每个图块上绘制图块的矩形、图块沿 x 轴的索引、设置背景颜色的时间(秒)和绘制图块的时间(秒)。如果一切正常,所有的瓷砖应该是相同的颜色。相反,这是我有时会看到的:

缩小后我似乎只看到了错误的结果。 问题可能与scrollViewDidEndZoomingupdateCanvas 在每次缩小时可能会被调用多次有关。编辑:不--不多次调用。)

【问题讨论】:

  • 这可能与 CATiledLayer 中的一个错误有关:如果在绘制瓦片的过程中调用“setNeedsDisplay”,则该瓦片不会被重绘。

标签: iphone cocoa-touch ipad ios catiledlayer


【解决方案1】:

有一个相当昂贵的 hack 可能对你有用:

tiledLayer.contents = nil;
[tiledLayer setNeedsDisplayInRect:tiledLayer.bounds];

如果我没记错的话,第一行实际上是把平铺层变成了普通层,但是第二行把它变回来了。但是,它会将平铺层中的所有内容都扔掉。

【讨论】:

  • 谢谢,但我不明白你把这段代码放在哪里。我看到的唯一可以访问平铺图层实例的地方是 drawLayer。如果我把代码放在那里,我的图层根本不会绘制。感谢您的帮助。
  • 你应该把它放在你现在做 setNeedsDisplay 的地方。平铺层是视图的根层:canvasView.layer。
猜你喜欢
  • 2010-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多