ios5:drawRect在CATiledLayer中为同一个Rect调用了两次 [英] ios5: drawRect called twice in CATiledLayer for the same Rect

查看:207
本文介绍了ios5:drawRect在CATiledLayer中为同一个Rect调用了两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了CATiledLayer的问题。它在iOS 4上运行完美,但在iOS 5上有问题。

I have a problem with a CATiledLayer. It is working perfect in on iOS 4, but has problems on iOS 5.

我的问题是 drawRect 是同时从两个不同的线程为同一个rect调用两次。由于我在此调用中加载图像,因此导致视图加载速度非常慢。

My Problem ist that drawRect is called twice for the same rect from two different threads at the same time. Since I load images in this call, it causes the view to load very slow.

2011-10-18 14:07:18.802 APP[12436:19003] drawRect:{{0, 400}, {368, 400}} (view:<TiledScrollColumn: 0x91bc880; frame = (0 1600; 368 5400); userInteractionEnabled = NO; layer = <CATiledLayer: 0x919c1b0>>)
2011-10-18 14:07:18.805 APP[12436:1b103] drawRect:{{0, 400}, {368, 400}} (view:<TiledScrollColumn: 0x91bc880; frame = (0 1600; 368 5400); userInteractionEnabled = NO; layer = <CATiledLayer: 0x919c1b0>>)

有没有人知道是什么原因造成的,或者我可以做些什么来解决这个问题?我没有对视图做特殊的事情,它基于photoscroller示例。

Has anyone an idea what could cause that or what I could do to fix that? I'm not doing special stuff with the view, it's based on the photoscroller example.

Bastian

推荐答案

我找到了解决方法。创建一个序列(一次只有一个操作)调度队列并在其中执行所有绘图,然后缓存结果。

I found a workaround. Create a serial (only one operation at at time) dispatch queue and perform all your drawing inside it, then cache the result.

我附加了代码我是使用,请注意我使用的是 CATiledLayer 的子类,而不是通过委托或其他技术绘制它。

I've attached the code I'm using, note I'm using a subclass of CATiledLayer, rather than drawing it through a delegate or other techniques.

我还创建了一个不确定的磁贴缓存,这可能会导致内存问题,具体取决于您的情况。您可能需要管理缓存中的切片数量,并在添加新切片时删除旧切片。收到低内存警告时,也应清除缓存。如果有人添加了这些改进,请随时编辑我的答案以包含它。

I'm also creating an indefinite tile cache, which may cause memory issues depending on your situation. You may need to manage the number of tiles in the cache, deleting old ones as new ones are added. The cache should also be cleared when a low memory warning is received. If anyone adds these improvements, please feel free to edit my answer to include it.

- (id)init
{
  if (!(self = [super init]))
    return nil;

  tileCache = [[NSMutableDictionary alloc] init];

  return self;
}

- (void)drawInContext:(CGContextRef)layerContext
{
  // CATiledLayer has a bug, where it spawns multiple threads for drawing, and then tries to draw the same tile multiple times simultaniously on separate threads
  // so we create our own serial background queue, and do dispatch_async on it. This will cache each draw operation, so multiple calls on one tile are efficient
  static dispatch_queue_t drawQueue = NULL;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
      drawQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
  });

  dispatch_sync(drawQueue, ^{

    // no map ways? draw nothing
    if (!self.mapWays)
      return;

    // load from cache?
    CGRect tileRect = CGContextGetClipBoundingBox(layerContext);
    NSString *tileCacheKey = [NSString stringWithFormat:@"%f%f%f%f", tileRect.origin.x, tileRect.origin.y, tileRect.size.width, tileRect.size.height];
    __block UIImage *tileImage;
    dispatch_sync(dispatch_get_main_queue(), ^{
      tileImage = [tileCache objectForKey:tileCacheKey];
    });
    if (tileImage) {
      CGContextDrawImage(layerContext, tileRect, tileImage.CGImage);
      return;
    }

    // prepare to draw the tile image
    UIGraphicsBeginImageContextWithOptions(tileRect.size, YES, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // filp coords
    CGContextTranslateCTM(context, 0, tileRect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);


    /*** do actual drawing here ***/


    // store tile in cache
    tileImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    dispatch_sync(dispatch_get_main_queue(), ^{
      [tileCache setObject:tileImage forKey:tileCacheKey];
    });

    // draw the tile
    CGContextDrawImage(layerContext, tileRect, tileImage.CGImage);
  });
}

这篇关于ios5:drawRect在CATiledLayer中为同一个Rect调用了两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆