iOS
Swift
UIAlertController
ViewController
Programming

How to present UIAlertController when not in a view controller?

Interview Questions practice on Codemia

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

Browse interview questions

Overview

When developing iOS applications, presenting user notifications is crucial for providing feedback and interaction cues. One common method to do this is by using UIAlertController. Traditionally, UIAlertController should be presented within a view controller, yet there are scenarios where you may wish to present it outside of the traditional view controller context. This article explores these situations and demonstrates how to correctly present an UIAlertController when not in a view controller.

Understanding UIAlertController

UIAlertController is a UIKit component used to present alerts and action sheets to the user. It is initialized with a title, a message, and a preferred style (alert or action sheet) and needs to be presented by a view controller using the present(_:animated:completion:) method.

Here's a basic example of presenting UIAlertController within a standard view controller:

swift
let alert = UIAlertController(title: "Alert", message: "This is an alert.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)

Situations Requiring Presentation Outside a View Controller

There are a few scenarios where you may need to present an alert outside the current view controller context:

  1. Global Error Handling: When an application needs to handle errors globally (e.g., network errors) that can occur anywhere.
  2. Background Tasks: While handling background tasks such as notifications received via AppDelegate or SceneDelegate.
  3. Utility Functions: Presenting alerts from utility functions/classes that do not have direct access to a specific view controller.

Technical Approach

Obtaining the Top View Controller

In order to present a UIAlertController without a direct reference to a view controller, you must first obtain a reference to the topmost view controller in the view hierarchy. Here's a method to do so:

swift
1func getTopViewController() -> UIViewController? {
2    guard let rootController = UIApplication.shared.keyWindow?.rootViewController else {
3        return nil
4    }
5    return findTopViewController(rootController)
6}
7
8func findTopViewController(_ controller: UIViewController) -> UIViewController {
9    if let presented = controller.presentedViewController {
10        return findTopViewController(presented)
11    }
12    if let navigation = controller as? UINavigationController {
13        return findTopViewController(navigation.visibleViewController ?? navigation)
14    }
15    if let tab = controller as? UITabBarController {
16        return findTopViewController(tab.selectedViewController ?? tab)
17    }
18    return controller
19}

Presenting UIAlertController

Once the top view controller is obtained, you can present the alert:

swift
1if let topController = getTopViewController() {
2    let alert = UIAlertController(title: "Global Alert", message: "This alert is presented from any context.", preferredStyle: .alert)
3    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
4    topController.present(alert, animated: true, completion: nil)
5}

Additional Considerations

Threads and Asynchronous Processes

When dealing with UI updates like presenting an UIAlertController, ensure you are on the main thread:

swift
1DispatchQueue.main.async {
2    if let topController = getTopViewController() {
3        // Present alert
4    }
5}

Scene Delegate (iOS 13+)

With the introduction of multi-window support from iOS 13, it's essential to consider which scene is active:

swift
1func getTopViewControllerForScene() -> UIViewController? {
2    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
3          let rootController = windowScene.windows.first?.rootViewController else {
4        return nil
5    }
6    return findTopViewController(rootController)
7}

Summary Table

Key PointDescription
Components InvolvedUIAlertController, UIViewController, UIApplication, DispatchQueue
Use CasesGlobal error handling, background tasks, utilities
Method to Obtain ViewControllerUse UIApplication to traverse view hierarchy to find topmost view controller
ConsiderationsEnsure operations are performed on the main thread, consider scene support for iOS 13+

Conclusion

While UIAlertController is traditionally presented by a view controller, certain scenarios require presenting alerts globally or from context-neutral locations. By leveraging methods to ascertain the topmost view controller, these alerts can be effectively presented. This approach allows applications to maintain robust user interaction patterns across a multitude of contexts, enhancing the overall user experience.


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.