Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is "var delegate: UIApplicationDelegate?" made an optional in UIApplication? That'd be a fatal error?

Were the delegate property ever to be nil, the app would be in an unrecoverable state.

class UIApplication

Declaration
unowned(unsafe) var delegate: UIApplicationDelegate?
Discussion
Every app must have an app delegate object to respond to app-related messages. For example, the app notifies its delegate when the app finishes launching and when its foreground or background execution status changes. Similarly, app-related messages coming from the system are often routed to the app delegate for handling. Xcode provides an initial app delegate for every app and you should not need to change this delegate later.

Why is UIApplicationDelegate.delegate defined as an optional? A nil value would be non-recoverable?

Actually, if I were to subclass UIApplication then I might be able to recover from delegate set to nil? Is this maybe why?

Here is a related question, but the AppDelegate is what holds the entire app together. I don't think it could be nil.

like image 917
Just Someone Avatar asked Aug 17 '16 22:08

Just Someone


1 Answers

One reason might be to prevent AppDelegate from messing up with your unit tests.

Normally, when you are running unit tests, you actually don't ever have to interact with any UI components drawn onto screen so, initializing application's window property is totally unnecessary. Moreover, the code written in AppDelegate.swift (such as function calls in application(application:didFinishLaunchingWithOptions) might cause your unit tests to not run as intended so you may want the application delegate to never be instantiated.

For a typical iOS application, UIKit creates the application with the following function in main.swift:

UIApplicationMain(Process.argc, Process.unsafeArgv, 
  NSStringFromClass(UIApplication), NSStringFromClass(AppDelegate))

(As of Xcode 6, it is handled by the @UIApplicationMain decorator.)

UIApplicationMain initializes the application object and the application delegate whose type is the class name you passed to it, and sets up the event cycle. It's totally up to you to have it create the delegate object for you. If you don't need AppDelegate's UIWindow property, or any callback methods about handling push notifications, application's state etc., you create the application without it:

UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(UIApplication), nil)

So that being said, if your unit tests don't depend on any of AppDelegate's methods to run, you can update main.swift as follows:

var delegateClassName: String? = NSStringFromClass(AppDelegate)

if NSClassFromString("XCTestCase") != nil {
 // Unit tests are being run, so don't execute any code written in AppDelegate.swift
 delegateClassName = nil
}
UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(UIApplication), delegateClassName)
like image 188
Ozgur Vatansever Avatar answered Nov 19 '22 02:11

Ozgur Vatansever