iOS development
UIViewController
iOS bug
user interface
iOS troubleshooting

presentViewControlleranimatedYES view will not appear until user taps again

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

If presentViewController does not visibly present until the user taps again, the usual problem is not the modal API itself. The real issue is that presentation is being requested at the wrong time, on the wrong thread, or while the main run loop is blocked from updating the UI.

Presentation Must Happen on the Main Thread

UIKit work belongs on the main thread. If presentation is triggered from a background callback, the behavior can become delayed or inconsistent.

swift
DispatchQueue.main.async {
    self.present(alertController, animated: true)
}

This is the minimum requirement, not the whole story. Main-thread dispatch fixes the execution context, but it does not fix lifecycle timing if you are presenting too early.

Do Not Present Before the View Is Ready

Presenting from viewDidLoad or from a controller that is not yet on screen often causes timing glitches. A safer lifecycle point is usually viewDidAppear if the presentation depends on the current controller already being visible.

swift
1override func viewDidAppear(_ animated: Bool) {
2    super.viewDidAppear(animated)
3
4    let vc = UIViewController()
5    vc.view.backgroundColor = .systemBackground
6    present(vc, animated: true)
7}

This works because the presenting controller is fully in the window hierarchy by that point.

Main-Thread Blocking Causes Delayed UI Updates

Another common reason is that the main thread is busy doing work immediately after the presentation call. In that case, the presentation request is queued, but the UI cannot animate or redraw until the main thread becomes free.

Problem pattern:

swift
self.present(vc, animated: true)
expensiveSynchronousWork()

If expensiveSynchronousWork() blocks the main thread, the modal may not appear until the run loop gets a chance to process UI updates, which can coincide with the next user interaction.

The fix is to move heavy work off the main thread.

Avoid Presenting During Another Transition

If one presentation, dismissal, or navigation transition is already happening, a second presentation can be ignored, delayed, or logged as a warning.

A safer pattern is to present only after the previous transition completes.

swift
self.dismiss(animated: true) {
    self.present(nextViewController, animated: true)
}

Or, if you are navigating and then presenting, wait until the current transition settles.

Common Safe Pattern for Async Callbacks

Many bugs happen after network calls or permission callbacks. The safe sequence is:

  1. Return to the main thread.
  2. Confirm the presenting controller is still visible.
  3. Present after the controller is in a stable state.
swift
1DispatchQueue.main.async {
2    guard self.view.window != nil else { return }
3    self.present(alertController, animated: true)
4}

The view.window check is a practical way to avoid presenting from a controller that is no longer active.

Check the Presentation Hierarchy

If the presenting controller is no longer the topmost visible controller, UIKit may reject or delay the presentation. Always confirm you are presenting from the controller that is actually active on screen.

Common Pitfalls

  • Calling present from a background queue.
  • Presenting too early in the controller lifecycle.
  • Blocking the main thread right after requesting presentation.
  • Trying to present while another transition is still in flight.
  • Assuming the extra tap caused the modal to work, when it really just gave the run loop time to update.

Summary

  • Delayed presentation is usually a timing or threading bug, not a mysterious UIKit failure.
  • Always present on the main thread.
  • Avoid presenting before the controller is actually on screen.
  • Keep heavy synchronous work off the main thread.
  • Make sure no other presentation or dismissal transition is competing with the one you want.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.