Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can 'downcasting' to AppDelegate ever fail?

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!

like image 328
M3nd3z Avatar asked May 24 '17 08:05

M3nd3z


2 Answers

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.

like image 50
vadian Avatar answered Oct 11 '22 13:10

vadian


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.

like image 32
Martin R Avatar answered Oct 11 '22 14:10

Martin R