Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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.</p> <p>I've attached the code I'm using, note I'm using a subclass of <code>CATiledLayer</code>, rather than drawing it through a delegate or other techniques.</p> <p>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.</p> <pre><code>- (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(&amp;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); }); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload