Search code examples
iosswiftcaanimation

When to add CAAnimation in a custom UIVIew?


The problem: my custom UIView animation shows only if I add the view in viewWillAppear or later.

The context: in my custom UIView I create and add the animation to the layer in my custom init function.

override init(color: UIColor) {
    backgroundPulsatingDotView = RouteIndicatorDotView(color: color)

    super.init(colour: color)

    configureBackgroundPulsatingDot()

    addPulsatingAnimation()
}

This custom UIView is deep inside the view hierarchy and ideally my view controller should not care to trigger the animation on its own or trigger the adding of view in viewWillAppear just because of this animation [besides other bugs which appear if using viewWillAppear or later stages for adding subviews]

Is there a way to still keep the logic of adding and starting the animation inside my custom view without needing a trigger from an external party which would say "hey now the view is visible, please animate yourself"?

Or where should I add the adding and starting of the animation inside my custom view lifecycle to make it work correctly with view controller life cycle?


Solution

  • Is there a way to still keep the logic of adding and starting the animation inside my custom view without needing a trigger from an external party which would say "hey now the view is visible, please animate yourself"?

    There is nothing to animate until the view is part of the app's view hierarchy and has been initially drawn. You can't animate until then. That is why you are sent events marking the view's life stages, so that you can put your code in the right method which will run at the the right time in the view’s like cycle. init is the wrong method. It is too early.

    Try overriding another lifetime method — perhaps something like layoutSubviews (though beware: this can be called many times, so you'll need to use a Bool flag so that you start the animation only the first time).

    Also note that even then you can't add the dot and start animating it all in one move. After adding it, you must wait for the redraw moment to pass before you start animating it. What I usually do is step out to main thread with a very short delay so that my animation code runs after the current CATransaction has committed.