How to Properly Access AppDelegate in Swift: An Optimization Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to Get a Reference to AppDelegate in Swift: From Simple to Advanced



If you've ever written iOS code in Swift, you've likely encountered a situation where you need to access AppDelegate. It seems simple, right? But this question has thousands of views on Stack Overflow, and for good reason. Behind the apparent simplicity lies a whole layer of architectural decisions that affect code performance and maintainability.



In this article, we'll cover not only the classic ways to get a reference to AppDelegate, but also discuss when it's truly necessary and when it's better to look for alternatives. Let's go!



The Classic Way: UIApplication.shared.delegate



The most common and perhaps the simplest way is to use the UIApplication.shared singleton. It looks like this:



if let appDelegate = UIApplication.shared.delegate as? AppDelegate {    // Now you have access to AppDelegate    appDelegate.someMethod()}


This code works, but it has a couple of nuances. First, we explicitly cast the type, which can lead to a crash if delegate turns out to be a different class. Second, this approach creates tight coupling in the code. In the world of modern iOS development, this is considered an anti-pattern, especially if you are using SwiftUI or SceneDelegate.



Optimization: Creating a Safe Wrapper



To avoid writing the type cast every time and to reduce risk, you can create a convenient extension. This not only simplifies the code but also improves its readability:



extension UIApplication {    static var appDelegate: AppDelegate? {        return shared.delegate as? AppDelegate    }}

// Usageif let appDelegate = UIApplication.appDelegate { appDelegate.performTask()}


Note: we use static var rather than a computed property each time. This slightly improves performance with frequent calls. The Swift compiler optimizes such constructs, giving you safe access without extra effort.



Alternative Approach: Through UIApplication.shared.delegate?.window??



Sometimes developers try to get AppDelegate through the window chain. It looks like this:



let appDelegate = UIApplication.shared.delegate?.window??.rootViewController


Honestly, this is not a good practice. First, window can be nil at app launch. Second, such code is hard to read and debug. Performance also suffers — each optional chaining requires additional checks. It's better to use the first method.



When is Access to AppDelegate Really Needed?



Before reaching for UIApplication.shared.delegate, ask yourself: "Do I really need this?" Often, AppDelegate is used for:



  • Managing the app lifecycle (launch, background transition, termination)
  • Configuring global services (Core Data, Firebase, analytics)
  • Handling push notifications and deep linking


But if you just need to pass data between screens or call a service, AppDelegate is the wrong choice. It's better to use Dependency Injection or singletons for specific services.



SwiftUI and AppDelegate: A New Perspective



With the arrival of SwiftUI, the approach to architecture has changed. Now we have @main and the App protocol. But what if you still need access to the old AppDelegate? You can use UIApplicationDelegateAdaptor:



@mainstruct MyApp: App {    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

var body: some Scene { Win

Blogs

Book Recommendations