I have a view controller controlling a main view with to sibling subviews. One is a view I call overlayView that has some buttons and labels and things from IB. The other is one called captureLayer that I programmatically add to hold an AVCaptureVideoPreviewLayer from a webcam. For some reason I can’t get the overlay layer to show on top of the preview layer.
This doesn’t work:
capturePreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession];
[self setCaptureView:[[NSView alloc] initWithFrame:[[self view] bounds]]];
// I know the order here is important and I think this is right
[[self captureView] setLayer:capturePreviewLayer];
[[self captureView] setWantsLayer:YES];
[[self view] addSubview:[self captureView] positioned:NSWindowBelow relativeTo:[self overlayView]];
[captureSession startRunning];
But I found out that putting the capturePreviewLayer in the main view, so the overlayView is a child instead of sibling to its view, does work:
capturePreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession];
[[self view] setLayer:capturePreviewLayer];
[[self view] setWantsLayer:YES];
[captureSession startRunning];
Any idea why? I’ve even done a very analogous thing using UIViews in iOS and didn’t see anything weird like this.
This is probably because your captureView is layer backed or layer hosting, while your overlay view is not. The overlayView draws directly to the window layer, and the captureView draws into a new layer on top of that.
The solution is to make the overlayView layer backed as well and use it’s zPosition if needed.
On iOS every view is layer backed by default so this problem won’t manifest itself there.