本文介绍了不是所有的瓷砖重绘后CATiledLayer -setNeedsDisplay的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的视图有一个 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);
// ...绘制上下文...
CGContextRestoreGState(context);
}

@end

MyViewController.m: p>

  @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:%f,[canvasView.layer bounds] .size.width / tileSize);
[canvasView.layer setNeedsDisplay];
}

@end

缩放后一直滚动视图,以确保每个磁贴都被看到。每当视图看起来不正确时,在下一次调用 -updateCanvas 时,预测的下一个rects更新大于实际的#of rects updated。会是什么原因?



编辑



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




我看起来似乎在缩小后看到错误的结果。 (Edit: No-- not called multiple times.)

解决方案

There is a rather expensive hack that might work for you:

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

If I recall correctly, the first line actually turns the tiled layer to an ordinary layer, but the second line turns it back. However, it’ll throw everything in the tiled layer away.

这篇关于不是所有的瓷砖重绘后CATiledLayer -setNeedsDisplay的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 08:21