Role of UIApplicationMain in iOS App Launch Process.

Venkatesh Yadav.P
4 min readJan 5, 2020

--

Credits: oleb.net

This article is about how the UIApplicationMain method contributes to the iOS App launch process.

During App launch, Once the initial setup like locating and loading app binary and linking required frameworks is done, the system must call into the binary code to start it running. But, what is the starting point?🤔

In objective-C, it was clear that the main function is the entry point. Our project would have a main.m file with the following Code.

int main(int argc, char *argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class]));
}
}

Here the main function does two things

  • It sets up a memory management environment, the @autoreleasepool and the curly braces that follow it.
  • It calls the UIApplicationMain function, which does the heavy lifting of helping your app pull itself up by its bootstraps and get running.

In Swift, It has no main function! Instead, Swift has a special attribute: @UIApplicationMain. We can see it in the AppDelegate class.

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
}

This attribute essentially does everything that the Objective-C main.m file was doing: it creates an entry point that calls UIApplicationMain to get the app started.

You are free to remove default @UIApplicationMain and substitute the main file. It can be Objective-C or Swift file. If you want to use a swift file, it should be named as main.swift. The file should contain essentially the Swift equivalent of the Objective-C call to UIApplicationMain. This file is the only place where it is allowed to put executable code at the top level outside any function body.

import UIKit
UIApplicationMain(
CommandLine.argc, CommandLine.unsafeArgv, nil,
NSStringFromClass(AppDelegate.self)
)

UIApplicationMain:

Regardless of whether you write your own main.swift file or rely on the Swift @UIApplicationMain attribute. you are calling UIApplicationMain. Calling this function is the primary thing the app does. Your entire app is nothing but a single gigantic call to UIApplication Main.

Here’s what happens when app launches and UIApplicationMain is called:

  • UIApplicationMain creates your app’s shared application instance, UIApplication: This is responsible for handling and routing user events to the respective objects, Every iOS app has exactly one instance of UIApplication. This is accessible in code using UIApplication.shared. The third argument in the UIApplicationMain call, a string, tells what class the shared application instance should be an instance of. If you pass nil it will be UIApplication by default.
  • UIApplicationMain also creates your applications instance’s delegate: Every app you write must have an app delegate instance. If we call UIApplicationMain manually we need to specify app delegate class in the fourth param. If we use the @UIApplicationMain attribute, it will part of the app delegate class declaration, and means: “This is the app delegate class!”. The declaration of UIApplicationDelegate in the UIApplication class looks as follows. You will be able to access it as UIApplication.shared.delegate.
open class UIApplication : UIResponder {
open class var shared: UIApplication { get }
unowned(unsafe) open var delegate: UIApplicationDelegate?
...
}
  • If the app has a main storyboard (which will be specified by application’s Info.plist file, with the key NSMainNibFile), UIApplicationMain will load it, tries to find out the view controller designated as the storyboard’s initial view controller, it instantiates this view controller, thus creating your app’s third instance.
  • If the app has a main storyboard, UIApplicationMain now creates your app’s window, an instance of UIWindow. It assigns this window instance as the app delegate’s window property. It assigns the initial view controller instance as the window’s rootViewController property. This controller is now the app’s rootViewController.
  • UIApplicationMain now turns to the app delegate and start calling some of its code, such as application(_:didFinishLaunchingWithOptions:). It is a good place to add some startup code, but don’t add any heavy work here.
  • If there is a main storyboard, UIApplicationMain now causes your app’s interface to appear. It does this by calling the UIWindow instance method makeKeyAndVisible.
  • Once the above method is called, the window is about to appear, now it will ask the root view controller to get its main view. If it gets the view from storyboard or xib, view’s nib file is loaded; its objects are instantiated and initialized, and they become the objects of the initial interface: the view is placed into the window, where it and its subviews are visible to the user. And viewDidLoad of the view controller will be called. The app is now launched and running!

And UIApplicationMain will continue running, just sitting there, watching for the user to do something, maintaining the event loop, which will respond to user actions as they occur.

The app can be developed without the main storyboard, in this case, things like creating a window instance, giving it a root view controller, assigning it to the app delegate’s window property, and calling makeKeyAndVisible on the window to show the interface, must be done by your code. As shown in the following example of the didFinishLaunchingWithOptions method of the AppDelegate class.

func application(_ application: UIApplication,didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey : Any]?)
-> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "TestVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
return true
}

Additional Information:

--

--