4

I have a CALayer that needs to display frames of video. Every time a frame is rendered (as a CGImageRef), this method is called:

- (void)displayFrame:(CGImageRef)frame {
    [view layer].contents = (id)frame;
}

What's strange is that this, at first, will not display anything. Every time view is resized, a new frame is displayed, but sticks until view is resized again.

How do I fix this?

jscs
  • 63,694
  • 13
  • 151
  • 195
spudwaffle
  • 2,905
  • 1
  • 22
  • 29

3 Answers3

5

Is displayFrame: being called on the main thread? If not then I have found that it will not always draw. You can try forcing it to update by using [CATransaction flush] like:

- (void)displayFrame:(CGImageRef)frame {
    [view layer].contents = (id)frame;
    [CATransaction flush];
}

If that does not work then you might try including the layer construction code to help identify any peculiarities with this layer.

Jon Steinmetz
  • 4,104
  • 1
  • 23
  • 21
  • Awesome! Thank you. It seemed that `displayFrame:` was not being called on the main thread. Using `[self performSelectorOnMainThread:@selector(displayFrame:) withObject:(id)frame waitUntilDone:NO];` cleared up the problem. – spudwaffle Aug 22 '11 at 05:07
2

You probably need to do [[view layer] setNeedsDisplay]. The drawing system needs to be informed that updates have been made and the screen needs to be repainted. Resizing a view does this, but it seems that changing a layer's contents might not.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • I added `[[view layer] setNeedsDisplay]` after `[view layer].contents = (id)frame` and I still get the same behavior. :( – spudwaffle Aug 21 '11 at 20:01
  • Well, crap. Try marking the view as needing display? `[view setNeedsDisplay:YES];` – jscs Aug 21 '11 at 21:34
0

Using [CATransaction flush]; did the trick for me. I have to figure out what (if any) performance hit I take for displaying text using this approach.

Stedy
  • 7,359
  • 14
  • 57
  • 77
Vimal Thilak
  • 2,510
  • 3
  • 14
  • 13