9

I have a view with a CATiledLayer backing. I want to take the visible tiles from this CATiledLayer UIView and add it to another view as its CALayer backing, thus recreating the visible image in another UIView that doesnt use CATiledLayer.

The reason I want to do this is I will use this second UIView to mask the effect of updating the CATiledLayer backed UIView - this currently produces a flicker as all tiles are re-loaded.

The problem is, I'm not totally sure how i would do this. Any ideas?

GWed
  • 15,167
  • 5
  • 62
  • 99
  • 1
    So you want to take a deliberately tiled view and make a normal view to hide the tiled view...? Maybe a crazy question but why was it tiled to start with? – Paul de Lange Jun 19 '12 at 06:55
  • @PauldeLange - When my tiled view is reloaded it 'flickers' as the tiles are re-drawn. There will be a UIView underneath the tiled view which will be a direct copy of the tiles above. Then when the tiles are reloaded, the bottom view will show through for a split second as the tiles are reloaded, thus stopping the flicker affect. From what I can tell this is a fairly common practice for graphics programmes - using a graphic buffer to smooth out the affects of rendering any new content above. – GWed Jun 19 '12 at 08:32
  • If you can render the background view faster than the tiles, why do you have tiles? affect -> effect by the way. – Paul de Lange Jun 19 '12 at 08:38
  • @pauldeLange - I could be wrong here, but I assume that the background layer would actually display quicker than the tiles can load and display because the tileLayer has to actually get the tiles, load them and display them. The background layer just has to redraw the pixels from the CATileLayers buffer - no additional processing required. Its just taking bits from memory and re-displaying them. Thats why i was wondering if it is possible to take the visible backing store of the CATiledLayer (i.e. the visible tiles stitched together) and assign it to the CALayer of another view to display? – GWed Jun 19 '12 at 16:43
  • 1
    @Gaz_Edge I have never seen any flickering with CATiledLayer. When you call "setNeedsDisplay" on it, it will keep the old image in place, and your "drawLayer:inContext:" will simply draw over it. You might want to show some more details on how you are drawing, and what properties on CATiledLayer you are setting. – fishinear Jun 27 '12 at 15:01
  • @fishinear what youre saying makes sense and its how i would assume tiling should work i.e no flicker. I'm actually implementing drawing code in drawRect. This may be my problem. Will try drawLayer method instead. – GWed Jul 10 '12 at 19:10
  • 1
    @Gaz_Edge that is correct. You must do the drawing in the drawLayer:inContext: of the delegate of the CATiledLayer. In my case that is always the view controller. – fishinear Jul 11 '12 at 10:59

2 Answers2

3

CATiledLayer is a subclass of CALayer providing a way to asynchronously provide tiles of the layer's content, potentially cached at multiple levels of detail.

You can render the visible things in the layer into a CGContextRef with:

- (void)renderInContext:(CGContextRef)ctx

And then use this to update your other layer by settings its delegate and implementing the

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context 

ss shown here http://www.raywenderlich.com/2502/introduction-to-calayers-tutorial

But honestly I don't think this is efficient.

Pochi
  • 13,391
  • 3
  • 64
  • 104
  • Thanks for the answer. You say it's not efficient. Do you have any other ideas that may help solve my flicker problem? – GWed Jun 26 '12 at 11:17
  • @Luis `renderInContext` doesn't seem to work on `CATiledLayer` as `CALayer` does for me. The tiles do not render at all. Any ideas? – Tim Oct 08 '12 at 10:34
0

Your real problem here is the flickering. I had a similar problem on a view with a custom CALayer backing it, this was part of the solution: Create a custom subclass of your CALayer and implement the following method:

- (void) display {
    self.contents = nil;
    [super display];
}

This fixed a set of problems for me, but may not fix it for you. The alternative for you may be to disable transactions while you update: From CATransaction Class Reference

setDisableActions: Sets whether actions triggered as a result of property changes made within this transaction group are suppressed.

So to use this:

[CATransaction begin];
[CATransaction setDisableActions:YES];
// do updating/flickering stuff
[self doFlickeringThing];
[CATransaction commit];
quellish
  • 21,123
  • 4
  • 76
  • 83