5

When working with CoreData, we need access to the shared store which is available via the AppDelegate. To obtain a reference to the AppDelegate we can get it by doing the following:

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

Why do we have to be so safe when downcasting to the Appdelegate? Can the downcast ever fail for some reason and if so, why?

I have looked around and can't find a reason as to why we write this code, and wanting to know why I write things will help!

abhi
  • 1,760
  • 1
  • 24
  • 40
M3nd3z
  • 316
  • 2
  • 12

3 Answers3

9

Optional downcasting to AppDelegate (actually to the class representing the application delegate class) will never fail because the application won't even launch if the application delegate class was missing.

You can 100% safely write

let appDelegate = UIApplication.shared.delegate as! AppDelegate

Many people suffer from exclamationmarkophobia and argue that all exclamation marks are evil and you always have to guard any optional. This is wrong. The world is not only black and white. There are many cases where forced unwrapping an optional is safe like in this particular case.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • Thank you so much Vadian. This is extremely helpful, believe me. I often avoid using force unwrapping as well, but its good to know that it is safe to use now and again. – M3nd3z May 24 '17 at 09:13
  • As of 2019, it's not phobia anymore, they banned it with error : Force Cast Violation: Force casts should be avoided. (force_cast) – Async- Jun 21 '19 at 09:23
  • @Async- Who is *they* and where does this error occur? – vadian Jun 21 '19 at 17:15
  • @vadian yeah sorry, it was actually SwiftLint in my case, I confused it with xcode error. – Async- Jun 22 '19 at 09:41
3

Adding the @UIApplicationMain attribute to a class

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { ... }

is equivalent to calling UIApplicationMain() in "main.swift" with "AppDelegate" as the name of the class from which the application delegate is instantiated:

UIApplicationMain(
    CommandLine.argc,
    UnsafeMutableRawPointer(CommandLine.unsafeArgv)
        .bindMemory(
            to: UnsafeMutablePointer<Int8>.self,
            capacity: Int(CommandLine.argc)),
    nil,
    NSStringFromClass(AppDelegate.self)
)

(compare e.g. What does "@UIApplicationMain" mean? and Subclass UIApplication with Swift).

With either method, an instance of the AppDelegate class is created and passed as delegate to the application object. So yes,

let appDelegate = UIApplication.shared.delegate as! AppDelegate

is safe.

But note that there is nothing special about the class name "AppDelegate", this is just convention. You can define the application delegate as

@UIApplicationMain
class MyFantasticAppDelegate: UIResponder, UIApplicationDelegate { ... }

in which case it of course would be

let appDelegate = UIApplication.shared.delegate as! MyFantasticAppDelegate

So the precise statement would be

Casting UIApplication.shared.delegate to the type of the class defined as application delegate cannot fail.

By convention, that type is AppDelegate, but it doesn't have to be.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
1

I can't agree with the point that force unwrapping downcasting to AppDelegate will never fail. It's isn't true. Because 'AppDelegate' could be the wrong type for your delegate. For example, I faced it when app used RxAppState framework. It has an extension for AppDelegate which returns 'RxAppState.RxApplicationDelegateProxy' class as the delegate. So always be careful.