475

How do I get a reference to AppDelegate in Swift?

Ultimately, I want to use the reference to access the managed object context.

stackich
  • 3,607
  • 3
  • 17
  • 41
AperioOculus
  • 6,641
  • 4
  • 26
  • 37
  • 9
    Note that some would consider use of the app delegate as a container for the managed object context or other "global" objects to be an anti-pattern. Consider having the app delegate pass the MOC to the controller, rather than making the controller find it. – Kristopher Johnson Jun 04 '14 at 19:49
  • 1
    @KristopherJohnson Hey Kris, how can I facilitate the AppDelegate injecting dependencies into view controllers? Instantiate the view controller programatically and use reflection to decide what to instantiate / inject, recursively? Are there any frameworks that can help with this? If I have to do this for every view controller manually, my AppDelegate is going to be huge! Oh, preferably without creating a factory for everything :) – Jimbo Mar 03 '18 at 19:35
  • 1
    A cursory search found [Swinject](https://github.com/Swinject/Swinject) which also has auto-wiring :) – Jimbo Mar 03 '18 at 19:41
  • 11
    For programmers who advise against putting anything "extraneous" in the app delegate, it's a bit nonsense because the Apple documentation explicitly states that a `"crucial role"` of the `UIApplicationDelegate` singleton is `"...to store your app’s central data objects or any content that does not have an owning view controller."` https://developer.apple.com/documentation/uikit/uiapplicationdelegate – trndjc Sep 22 '18 at 08:57

18 Answers18

838

The other solution is correct in that it will get you a reference to the application's delegate, but this will not allow you to access any methods or variables added by your subclass of UIApplication, like your managed object context. To resolve this, simply downcast to "AppDelegate" or what ever your UIApplication subclass happens to be called. In Swift 3, 4 & 5, this is done as follows:

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let aVariable = appDelegate.someVariable
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
  • 11
    In case anyone is still having problems, targeting OS X requires you to import Cocoa for this to work for NSApplication.sharedApplication(). I'd guess that iOS would need the equivalent. – smaurice Jun 09 '14 at 20:47
  • 2
    This is the more useful of the two answers. – Joe Jun 14 '14 at 14:25
  • Thanks, your snippet does work for me, but I find that I am also able to simply call *AppDelegate().someVariable*... is that a bad idea (maybe not leveraging a shared instance)? Is there a reason why it would be better to declare a constant reference to it as per your (let) example? – zacjordaan Jun 27 '14 at 10:17
  • 3
    @zacjordaan Using that method, you will get autocompletion for the property, but it won't actually work. That way will create a new instance of the AppDelegate class every time you use it. You're better off using the delegate accessible through the sharedApplication singleton. And as far as your second question goes, yes you probably want to use a constant. Even though, you may be changing the AppDelegate's properties, you probably won't be reassigning the pointer to anything else, in which case, there's no need for a variable. This is completely up to you though. Do what suits your needs. – Mick MacCallum Jun 27 '14 at 13:30
  • 2
    Excellent advice! I had mistakenly thought that AppDelegate() was singleton but after thinking about what you've said I've realized that if it was then there wouldn't be a sharedApplication pattern for us to use in this way. Of course I don't want to spawn unnecessary instances if I don't have to, so your constant declaration will suit perfectly; Thank you. – zacjordaan Jun 27 '14 at 14:07
  • I tried this but Xcode complains: "Use of undeclared type: AppDelegate". What might I be missing? – CBGrey Jul 01 '14 at 15:12
  • @CBGrey This assumes that your app delegate's class is "AppDelegate." If it's anything different, substitute that in instead. – Mick MacCallum Jul 01 '14 at 15:15
  • I believe it is: @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { – CBGrey Jul 01 '14 at 15:17
  • 1
    "cleaning" the project and rebuilding resolved this for me. Thanks for the help. – CBGrey Jul 01 '14 at 15:23
  • 2
    And btw. - don't forget to 'import UIKit' if you're not in a ViewController or anything else that is importing it already – Thomas Fankhauser Oct 01 '14 at 14:49
  • I got this error too: "Use of undeclared type: AppDelegate". In my case, the error was because AppDelegate.swift was not included on my Tests target Compile Sources list. – Eneko Alonso Mar 21 '15 at 04:14
  • 1
    *Swift 3.0* (in later Xcode8 betas- notice `shared` is no longer a function call) `let delegate = UIApplication.shared.delegate as! AppDelegate` – popcnt Aug 16 '16 at 20:38
  • Why are we casting it to AppDelegate, I mean shouldn't it just return as AppDelegate type which also conforms to `UIApplicationDelegate?` ? Why is apple putting us to such trouble? Investigating further when I ctrl + click onto delegate it shows `unowned(unsafe) public var delegate: UIApplicationDelegate?` trying to make sense of this, my conclusion is: as if its identity is more coming from its protocol-ness...but again can't understand why it's simply not already `AppDelegate` subclass!? – mfaani Nov 28 '16 at 18:59
  • MEMO: It can't get the value when the someVariable declare to weak. sample:@property (weak, nonatomic) NSString *someVariable; Chang to strong will be work. – 米米米 Jan 11 '17 at 02:09
  • can I call a method to view controller from appdelegate – iOS Developer Mar 26 '18 at 05:38
  • 5
    I don't want to add this as separate answer, but to get AppDelegate with your own methods, properties in project where both a Swift and an Obj-c are used You should add #import "AppDelegate.h" to "ProjectName-BridgingHeader.h" – Marcin Mierzejewski Feb 08 '19 at 11:19
54

Swift 4.2

In Swift, easy to access in your VC's

extension UIViewController {
    var appDelegate: AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
   }
}
Karan Thakkar
  • 1,007
  • 5
  • 24
  • 41
DogCoffee
  • 19,820
  • 10
  • 87
  • 120
40

Convenience Constructors

Add in AppDelegate Class at the end of code

Swift 5.7

 func appDelegate() -> AppDelegate {
    guard let delegate = UIApplication.shared.delegate as? AppDelegate else {
        fatalError("could not get app delegate ")
    }
    return delegate
 }

To use AppDelegate reference anywhere in code?


For example: Call AppDelegate Method named setRoot

appDelegate().setRoot()

Scene Delegate Example:

func sceneDelegate() -> SceneDelegate {
    guard let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate else {
      fatalError("could not get scene delegate ")
    }
   return sceneDelegate
}
AiOsN
  • 2,305
  • 2
  • 23
  • 29
  • 2
    Would be great to explain what setRoot() does and when to call it. e.g. is it ok to call it from a ViewController? From a Unit test where window is not set yet? More context would be great. – Houman Dec 24 '19 at 16:52
  • @Houman setRoot is method from AppDelegate which could be used to switch between multiple Roots or ParentViewController and could be any method. Discussion is about how to get the reference of AppDelegate to further access, but hope setRoot must be clear as well. – AiOsN Dec 26 '19 at 05:46
24

This could be used for OS X

let appDelegate = NSApplication.sharedApplication().delegate as AppDelegate
var managedObjectContext = appDelegate.managedObjectContext?
jiminybob99
  • 857
  • 1
  • 8
  • 15
21

It's pretty much the same as in Objective-C

let del = UIApplication.sharedApplication().delegate
Connor Pearson
  • 63,902
  • 28
  • 145
  • 142
17

Here is the Swift 5 version:

let delegate = UIApplication.shared.delegate as? AppDelegate

And to access the managed object context:

    if let delegate = UIApplication.shared.delegate as? AppDelegate {

        let moc = delegate.managedObjectContext
        
        // your code here
        
    }

or, using guard:

    guard let delegate = UIApplication.shared.delegate as? AppDelegate  else {
        return
    }

    let moc = delegate.managedObjectContext
        
    // your code here
    
Alex Terente
  • 12,006
  • 5
  • 51
  • 71
Paul Ardeleanu
  • 6,620
  • 2
  • 40
  • 41
15

Appart from what is told here, in my case I missed import UIKit:

import UIKit
12

SWIFT < 3

Create a method in AppDelegate Class for ex

func sharedInstance() -> AppDelegate{
        return UIApplication.sharedApplication().delegate as! AppDelegate
    }

and call it some where else for ex

let appDelegate : AppDelegate = AppDelegate().sharedInstance()

SWIFT >= 3.0

func sharedInstance() -> AppDelegate{
    return UIApplication.shared.delegate as! AppDelegate
}
Dharmbir Singh
  • 17,485
  • 5
  • 50
  • 66
  • 2
    this also works, and i like the idea of the sharedInstance naming. thanks! – John Griffiths Jun 22 '16 at 01:03
  • 2
    Your example would still instantiate a new `AppDelegate` object every time you called `AppDelegate().sharedInstance()` – pxpgraphics Nov 13 '16 at 06:37
  • 1
    I like this solution better than the accepted one (which is "unsiwftly" verbose if you have to use it all over). I was thinking about experimenting with an `extension` for `NSApplication` before I found this answer, but this is much better. Nowadays you would probably want to use a class computed read only property `shared` though, maybe you would like to post an update for Swift 3? – Patru May 25 '17 at 23:41
  • 1
    I am actually in the process of refactoring my code to use `static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } }` which is more in line with the developing Swift 3 style of using computed read only properties for this type of things. I will probably be able to drop the `?` once the refactoring is done, don't you think? (Sorry, code formatting in comments is always a mess.) – Patru May 26 '17 at 07:25
  • @ pxpgraphics UIApplication is a singleton class so no need to worry about multiple instantiation. – Abhijith Dec 04 '17 at 09:57
8

Try simply this:

Swift 4

// Call the method
(UIApplication.shared.delegate as? AppDelegate)?.whateverWillOccur()

where in your AppDelegate:

// MARK: - Whatever
func whateverWillOccur() {

    // Your code here.

}
7
  1. Make sure you import UIKit

  2. let appDelegate = UIApplication.sharedApplication().delegate! as! AppDelegate

pkamb
  • 33,281
  • 23
  • 160
  • 191
Sachin Nikumbh
  • 911
  • 11
  • 11
7

Here's an extension for UIApplicationDelegate that avoids hardcoding the AppDelegate class name:

extension UIApplicationDelegate {

    static var shared: Self {    
        return UIApplication.shared.delegate! as! Self
    }
}

// use like this:
let appDelegate = MyAppDelegate.shared // will be of type MyAppDelegate
nyg
  • 2,380
  • 3
  • 25
  • 40
  • on the Mac for `NSApplicationDelegate` this gives me: `'Self' is only available in a protocol or as the result of a method in a class; did you mean 'AppDelegate'?`. Is this outdated? – pkamb Nov 05 '19 at 23:03
  • @pkamb I've just tried it in a new project and I don't have this error. I replaced `UIApplicationDelegate` by `NSApplicationDelegate` and `UIApplication` by `NSApplication`. – nyg Nov 07 '19 at 18:52
5

it is very simple

App delegate instance

let app = UIApplication.shared.delegate as! AppDelegate

you can call a method with one line syntax

app.callingMethod()

you can access a variable with this code

app.yourVariable = "Assigning a value"
Daniel Puiu
  • 962
  • 6
  • 21
  • 29
Harendra Tiwari
  • 460
  • 5
  • 11
4
extension AppDelegate {

    // MARK: - App Delegate Ref
    class func delegate() -> AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }
}
CrazyPro007
  • 1,006
  • 9
  • 15
3

In my case, I was missing import UIKit on top of my NSManagedObject subclass. After importing it, I could remove that error as UIApplication is the part of UIKit

Hope it helps others !!!

NSPratik
  • 4,714
  • 7
  • 51
  • 81
3

I use this in Swift 2.3.

1.in AppDelegate class

static let sharedInstance: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

2.Call AppDelegate with

let appDelegate = AppDelegate.sharedInstance
Ted Liu
  • 31
  • 1
2

In Swift 3.0 you can get the appdelegate reference by

let appDelegate = UIApplication.shared.delegate as! AppDelegate
Ramakrishna
  • 712
  • 8
  • 26
2

As of iOS 12.2 and Swift 5.0, AppDelegate is not a recognized symbol. UIApplicationDelegate is. Any answers referring to AppDelegate are therefore no longer correct. The following answer is correct and avoids force-unwrapping, which some developers consider a code smell:

import UIKit

extension UIViewController {
  var appDelegate: UIApplicationDelegate {
    guard let appDelegate = UIApplication.shared.delegate else {
      fatalError("Could not determine appDelegate.")
    }
    return appDelegate
  }
}
Josh Adams
  • 39
  • 3
1

In the Xcode 6.2, this also works

let appDelegate = UIApplication.sharedApplication().delegate! as AppDelegate

let aVariable = appDelegate.someVariable
pkamb
  • 33,281
  • 23
  • 160
  • 191
v01d
  • 569
  • 6
  • 10