CALayer behaves differently when creating anew vs when applying CATransform3dIdentity

71 views Asked by At

I am really stuck with some CALayer knowledge missing.

I have a layer which knows how to draw an arrow.

I apply some transform on every frame on it.

But it only works as expected if I always create this layer from scratch and apply the transform. And it doesn't work if I try reusing the same old layer (by applying a CATransform3dIdentity). Through "it doesn't work" I mean it flickers on the screen and the transform is not applied as needed as compared to the transform applied to the newly created layer.

My code looks as follows:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    transformModel = [OverlayTransformExtractor transformFromPixelBuffer:sampleBuffer];

    if(transformModel)
    {
        //I tried also not removing it every time but just transforming.. the effect is the same
        [firstLayer removeFromSuperlayer];

        if(!firstLayer)
        {
            firstLayer = [VNArrowLayer layer];

            firstLayer.frame = CGRectMake(videoView.frame.origin.x, videoView.frame.origin.y, videoView.frame.size.width, videoView.frame.size.height);
            originalTransform = firstLayer.transform;
        }

        //resetting the previous transforms
        firstLayer.transform = CATransform3DIdentity;

        [self applyTransform:transformModel.transform];

        dispatch_async(dispatch_get_main_queue(), ^(void)
        {
            [arrowView.layer addSublayer:firstLayer];

            [CATransaction begin];
            [CATransaction setValue:(id)kCFBooleanTrue
                             forKey:kCATransactionDisableActions];
            [firstLayer setNeedsDisplay];
            [CATransaction commit];

        });
    }
    else
    {
        dispatch_async(dispatch_get_main_queue(), ^
        {
          [firstLayer removeFromSuperlayer];
            [secondLayer removeFromSuperlayer];
        });
    }
}

Some suggestions of why is it behaving differently when it's just created? I checked the transform to be the same. I even tried to set the same position as a new layer (0,0), but the it is even more weird (it remains in the left top corner)

I also thought that maybe it's because of the implicit animation, so I tried turning it off -> no change.

Adding a new layer every time is not acceptable. The memory becomes full pretty fast, even though I manually try setting the firstLayer to nil.

1

There are 1 answers

0
Fawkes On

So as stated above when I was applying a transform to existing layer (at every frame) it flickered. When creating it at every frame it was perfect, but memory intensive.

I could not get what makes it flicker, maybe some constraints or layout stuff about which I cannot find any information but..

I managed to make the approach (new layer at every frame) work. The idea was, I was removing the old layer and assigning nil to it not on the main thread, which cause the deallocations to happen late after and in this way to fill my memory quickly.

So the solution is to remove the old layer, to create the new one and to apply the transform on the main thread.

If smb can provide an answer that explains the flickering, I'll be glad to mark it as a correct one.