iphone - 在 CATiledLayer -setNeedsDisplay 之后,并非所有图 block 都重绘

标签 iphone cocoa-touch ipad ios catiledlayer

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

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

Canvas View .h:

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

Canvas View .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

测试此功能时,我总是在缩放后一直滚动整个 View ,以确保看到每个图 block 。每当 View 看起来不对时,在下一次调用 -updateCanvas 时,预测的“下一个更新的 rects 数”大于实际的“更新的 rects 数”。什么会导致这个?

编辑:

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

Screenshot of tiles with mismatched colors Screenshot of tiles with mismatched colors

缩小后我似乎只看到错误的结果。 这个问题可能与 scrollViewDidEndZooming 以及 updateCanvas 每次缩小时会被调用多次有关。 (编辑:否——未多次调用。)

最佳答案

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

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

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

关于iphone - 在 CATiledLayer -setNeedsDisplay 之后,并非所有图 block 都重绘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5198155/

相关文章:

xcode - iPad:检测外接键盘

iphone - UIImageView setImage 在 iPad 上无法工作,但在 iPhone 上工作正常

iphone - 计算UIScrollView的位置

ios - 我可以忽略 "Unable to simultaneously satisfy constraints"吗?

iphone开发-豹子还是雪豹?

ios - UISearchController:searchBar 和 scopeBar 在第一次触摸事件时重叠

ios - iOS 7 是否支持 Applescript?

Iphone-SDK : accelerometer x, z 到 360 度?

ios - 如何以编程方式使用自动布局排列这三个 UILabel?

ios - 是否可以使用 iOS AutoLayout 创建基于动态网格的布局?