Click here to Skip to main content
14,038,727 members
Click here to Skip to main content
Add your own
alternative version


4 bookmarked
Posted 20 May 2014
Licenced CPOL

iOS Tricks: UIView with Additional sublayers - Applying the Same Implicit Animation Rules that the Main Layer Uses

, 21 May 2014
Rate this:
Please Sign up or sign in to vote.
When you add additional layers to a UIView, those new layers don't animate in the same way that the UIView's Backing Layer does. I have a trick that fixes this gotcha good and proper.


When you add additional layers to a UIView, those new layers don't animate in the same way that the UIView's Backing Layer does. I have a trick that fixes this gotcha good and proper.


An implicit animation is an animation which happens automatically when changing a property on a view or layer.

Every UIView has a main/backing CALayer. When a property of a CALayer is changed, it queries its delegate (the UIView) for an animation to use for that change (actionForLayer:forKey:) and since a view is the delegate for its layer, the layer queries its view for any custom animations actions that would be required. The view manages all its layers' implicit actions.

This all happens automatically with a normal UIView -> CALayer relationship. However if you add additional layers to an existing view, the new layers don't have any delegate set.

Now why not just set the new layer's delegate to the owning view, I hear you ask?

That unfortunately doesn't won't work because a layer also controls its owning view via the delegate and if there's more than one layer controlling the view, weird things start to happen.

Using the owning view is the correct idea though;

Actually, if you only send the new layer's actionForLayer:forKey: messages to the view, then the layer applies implicit animations correctly, and the view is not effected by the additional layers.

To do this, I've created a class to use as the layer's delegate.

The Class

#import <Foundation/Foundation.h>

@interface LGLayerActionsForwarder : UIView

- (instancetype) initWithView: (UIView *) view;

@property (nonatomic, readonly) UIView *view;

#import "LGLayerActionsForwarder.h"

@implementation LGLayerActionsForwarder
    __weak UIView *_view;

- (instancetype) initWithView: (UIView *) view
    self = [super init];
    if (!self) return nil;

    _view = view;

    return self;

- (id <CAAction>) actionForLayer: (CALayer *) layer forKey: (NSString *) event
    return [_view actionForLayer: layer forKey: event];


How to Use the Class

Create an instance of the LGLayerActionsForwarder class and assign it to all the layers you create.

_actionsForwarder = [[LGLayerActionsForwarder alloc] initWithView: self];

_yellowLayer = [CALayer layer];
_yellowLayer.delegate = _actionsForwarder;

In the CustomViewLayer example _yellowLayer is aligned to the view's frame on layoutSubviews, but would normally animate when the view is re-layed out because of a size change.

But, by assigning a delegate to the layer...

_yellowLayer.delegate = _actionsForwarder;

...the layer stop's animating on every change and behaves the same as the view's backing layer, which only animates within animation block. ([UIView animateWithDuration:animations:])

@implementation CustomViewWithLayer
    CALayer *_yellowLayer;
    LGLayerActionsForwarder *_actionsForwarder;

- (id) initWithCoder: (NSCoder *) coder 
    self = [super initWithCoder: coder];
    if (!self) return nil;

    // create a forwarder instance and link it to the view
    // NOTE: If you comment out just this line, then the yellow layer would function as a normal layer (animating).
    _actionsForwarder = [[LGLayerActionsForwarder alloc] initWithView: self];

    _yellowLayer = [CALayer layer];
    _yellowLayer.borderColor = [UIColor blueColor].CGColor;
    _yellowLayer.borderWidth = 1;
    _yellowLayer.cornerRadius = 20;
    _yellowLayer.delegate = _actionsForwarder;
    _yellowLayer.backgroundColor = [UIColor yellowColor].CGColor;

    [self.layer addSublayer: _yellowLayer];

    return self;

- (void) layoutSubviews
    [super layoutSubviews];

    _yellowLayer.frame = self.bounds;



  • Initial version


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Leslie Godwin
Technical Lead FNB Connect
South Africa South Africa
iOS Technical Lead at FNB

Computers are really sweet. Aren't they?
Yup they are...

I've always loved writing tools and components...never been very interested in playing games....always wanted to be able to write them though.

And, yes. I'm still pretty annoyed they discontinued the Amiga computer.

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
KarstenK3-Aug-18 0:21
mveKarstenK3-Aug-18 0:21 
Small but useful, really THATS what I needed. Smile | :)
GeneralMy vote of 5 Pin
Volynsky Alex9-Dec-14 19:15
professionalVolynsky Alex9-Dec-14 19:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.190425.1 | Last Updated 21 May 2014
Article Copyright 2014 by Leslie Godwin
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid