viewDidAppear in iOS — what it is, when it’s called and examples

Author: IT Sectr Published: 2026-03-05 Reading time: 8 min

viewDidAppear is a UIViewController method that UIKit calls after the screen has fully appeared on the display and all transition animations are complete. According to Apple Developer Documentation, this method guarantees that the View is visible to the user and ready for interaction. viewDidAppear is the optimal place to start animations, tracking, and asynchronous operations.

Key Takeaways

  • viewDidAppear is called after the screen fully appears and animations complete
  • Used for starting animations that should begin after appearing
  • Sending screen view analytics is a standard task for viewDidAppear
  • Suitable for starting asynchronous operations: loading content, starting timers
  • super.viewDidAppear is required for proper operation of parent controllers

What is viewDidAppear

viewDidAppear is a UIViewController method that UIKit calls after the View has been added to the window hierarchy and the transition animation has fully completed. At this point, the screen is in its final state: it is visible, interactive, and all UIKit animations have stopped. The developer overrides this method to perform actions that require the screen to be guaranteed in front of the user’s eyes.

Unlike viewWillAppear, where the screen is only preparing to show, viewDidAppear signals that the user already sees the interface. This is a critical difference: starting an animation in viewWillAppear can cause dropped frames because UIKit is still processing the transition. In viewDidAppear, the transition is complete, and the controller’s resources can be used to render new content.

The method accepts an animated parameter of type Bool, similar to viewWillAppear. If true, the screen appearance was accompanied by animation. This parameter can be used to adapt UI behavior: for example, skipping an entrance animation during a non-animated return.

When viewDidAppear is called

viewDidAppear is called in all scenarios where the screen has completed its appearance process. Let’s look at the main cases from an iOS developer’s perspective.

When a navigation transition completes

After UINavigationController finishes a push or pop animation, viewDidAppear is called on the target controller. For the first screen in the stack, it fires after the initial opening animation. This is the main scenario, and it is what developers primarily target when placing logic in viewDidAppear.

After dismissing a modal

When the user dismisses a modally presented controller and returns to the previous one, UIKit calls viewDidAppear on the returning controller. The animated parameter will correspond to whether the dismiss was performed with animation. This moment is important for updating the UI after receiving data from a child screen.

swift
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    logScreenView()
    startOnboardingAnimation()
}

When switching TabBar tabs

UITabBarController calls viewDidAppear on the controller of the selected tab after the switch animation completes. This differs from viewWillAppear, which fires when the switch begins. If a tab has a welcome animation or you need to track active time, viewDidAppear is the right place.

When coming from background

When the app returns from background to foreground, the visible controller may have viewWillAppear and viewDidAppear called if the View’s lifecycle was temporarily suspended. However, for reliable tracking of returning from the background, use UIApplication.willEnterForegroundNotification separately.

Practical tasks in viewDidAppear

viewDidAppear handles tasks that require a visible screen for correct execution. Let’s look at key usage scenarios in real projects.

Sending analytics events

The most common task for viewDidAppear is tracking screen views. Analytics systems such as Firebase Analytics, Amplitude, or Mixpanel should receive events only after the screen is actually shown to the user. Sending an event in viewWillAppear can underestimate viewing time and create false triggers.

swift
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    Analytics.logEvent(
        name: "screen_view",
        parameters: [
            "screen_name": "ProfileScreen",
            "screen_class": String(describing: self)
        ]
    )
}

Starting entrance animations

Animations that should begin after the screen appears — staggered element appearance, parallax, tutorials — are started in viewDidAppear. At this point, the graphics context is fully ready, and the animation will be smooth, without frame drops at the start. This is especially important for animations using UIViewPropertyAnimator.

Starting async loading

Heavy asynchronous operations — loading high-resolution images, parsing large JSON, initializing video — are better started in viewDidAppear rather than in viewDidLoad or viewWillAppear. By the time the method is called, the user already sees the interface, so you can show a skeleton or loader without delaying screen appearance.

Starting timers and intervals

If the screen has elements requiring periodic updates — countdown timer, progress indicator, progress animation — they are started in viewDidAppear and stopped in viewDidDisappear. This prevents timers from running when the screen is not visible, saving battery life and CPU resources.

Starting content playback

Media content — video, audio, Lottie animations — is started in viewDidAppear, not earlier. If you start playback in viewWillAppear, the user will miss the first seconds while the screen is still appearing. In viewDidAppear, you can start an AVPlayer or Lottie animation with confidence that the user sees the content from the first frame. This is especially important for onboarding screens and splash screens where precise timing matters.

Animations and performance

The right timing for starting an animation directly affects the perception of interface smoothness. The difference between starting in viewWillAppear and viewDidAppear may be unnoticeable for simple animations but becomes critical for complex scenes.

When UIKit performs a push transition between screens, it takes screenshots, animates them, and simultaneously calls viewWillAppear on the new controller. If you start a heavy animation at this point — parallax, blur, transformation — UIKit may drop frames of the transition animation, creating a jerky effect. viewDidAppear guarantees that the transition animation is complete, giving you full control over rendering.

swift
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    UIView.animate(
        withDuration: 0.6,
        delay: 0.3,
        usingSpringWithDamping: 0.8,
        initialSpringVelocity: 0.5
    ) {
        self.cardView.alpha = 1.0
        self.cardView.transform = .identity
    }
}

Use delays and damping to create a natural cascading appearance of elements. This approach improves interface perception and increases dwell time — users spend more time exploring content, which positively impacts behavioral metrics.

Common mistakes in viewDidAppear

Incorrect use of viewDidAppear can lead to performance issues, unexpected animation behavior, and excessive tracking. Let’s look at common mistakes.

The first mistake is multiple calls. viewDidAppear can be called several times in certain scenarios: switching tabs, returning from the background, modal transitions. If the method performs a heavy operation without a flag check, it will be duplicated. Use a hasAppeared flag or dispatchOnce for one-time actions.

The second mistake is starting network requests without cancellation on hide. If the user leaves the screen before the request completes, the result may be applied to an already hidden View. Use cancellable URLSessionTask and cancel them in viewDidDisappear.

The third mistake is tracking in viewWillAppear instead of viewDidAppear. Some developers send analytics events in viewWillAppear, but this creates false triggers if the screen didn’t appear (for example, due to a cancelled pop gesture). viewDidAppear is the only reliable indicator that the user actually saw the screen.

The fourth mistake is forgetting super. Calling super.viewDidAppear is necessary for proper operation of UINavigationController, UITabBarController, and UISplitViewController. Without it, standard navigation and interface update mechanisms may break.

The fifth mistake is changing orientation or screen size without considering viewDidLayoutSubviews. If your animation in viewDidAppear depends on the final View dimensions, remember that viewDidLayoutSubviews may have been called multiple times before viewDidAppear. On the first screen appearance, layout completes before viewDidAppear is called, but on subsequent size changes — for example, on device rotation — viewDidAppear may not be called, and your animation won’t start. In such cases, use viewDidLayoutSubviews with a firstLayout flag check.

Proper implementation involves keeping a reference to the animation object and explicitly cancelling it when leaving the screen. The sixth mistake is starting infinite animations without a stop flag. If you start a repeating animation in viewDidAppear (e.g., a pulsing indicator or spinning loader) but don’t stop it in viewDidDisappear, the animation will consume GPU resources even when the screen is hidden. Always keep a reference to the active animation and call removeAllAnimations or setCompletion in the corresponding lifecycle method.

The seventh mistake is ignoring viewDidDisappear for stopping activities. If you started listening to GPS, accelerometer, or gyroscope in viewDidAppear, be sure to stop it in viewDidDisappear. Otherwise, sensors will continue working in the background, draining the battery, even if the user has long moved to another screen. Use paired start and stop calls in the corresponding lifecycle methods — this guarantees correct resource management on the device.

Frequently Asked Questions

What’s the difference between viewDidAppear and viewWillAppear?

viewWillAppear is called before the appearance animation, when the screen is not yet visible. viewDidAppear is called after the animation fully completes, when the screen is visible and available for interaction.

Why is it better to start animations in viewDidAppear?

In viewDidAppear, the UIKit transition animation has already finished, and all rendering resources are available to your controller. Starting animations earlier can lead to dropped frames and a jerky interface.

Can viewDidAppear be called without viewWillAppear?

In a normal lifecycle, no — viewDidAppear always follows viewWillAppear. However, in certain state restoration scenarios, the system may call only viewDidAppear.

How to avoid analytics duplication in viewDidAppear?

Add a flag check for firstAppearance or use a combination of a counter and screen name. For example, send the screen_view event only when firstAppearance = true, then reset the flag.

What happens when viewDidAppear is called from the background?

When returning from the background, UIKit may call viewDidAppear on the visible controller if the View was unloaded from memory. For reliable tracking, use AppDelegate notifications.

Summary

  • viewDidAppear is called after the screen fully appears and all transition animations complete
  • Optimal place for sending analytics screen views and user events
  • Start animations in viewDidAppear for smoothness and to avoid dropped frames
  • Initiate heavy async operations after appearance to avoid delaying rendering
  • Start timers and intervals in viewDidAppear and stop them in viewDidDisappear
  • Use flags or counters to prevent duplication of one-time actions
  • Always call super.viewDidAppear for proper navigation and parent controller operation

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also