The iOS App Life Cycle
What happens when a user clicks on an app to launch it? How does tapping on an icon from the home screen actually get to my code running in a ViewController?
Why is it useful to know what the App Life Cycle is? Well, when you know how a tool is working underneath the hood, you're able to make informed decisions about how to best use it!
To illustrate this with an example, think of a bottle flip.
Some people just throw the bottle into the air, hoping it'll land correctly. However, if you know the physics behind the bottle flip (angular momentum and fluid dynamics), you're able to make informed decisions about the manner in which you throw the bottle, and are more aware of the subtlties that affect the result -- like how much water is in the bottle.
How does this relate back to the App Life Cycle? By knowing the processes at work underneath the hood, you'll be able to bring your attention to subtlties while programming and while debugging. So, what's actually happening when a user clicks on an app icon?
Let's begin with a blurb from Apple's documentation:
Apps are a sophisticated interplay between your custom code and the system frameworks. The system frameworks provide the basic infrastructure that all apps need to run, and you provide the code required to customize that infrastructure and give the app the look and feel you want. To do that effectively, it helps to understand a little bit about the iOS infrastructure and how it works.
When creating a project in XCode, Apple provides the basic components of an iOS app, which is already set up to work with their system frameworks.
However, their starter project is a blank canvas.
In order to make it into the app you want it to be, you have to customize it through your own views, data models, and the interactions between the two.
But before our code in the ViewController is even executed, there is quite a bit of setup done for us already.
The entry point for any C-based app is called
main. In other words, the first function that is called in an iOS application is the
main function. Specifically in iOS apps, however, this function comes with our project, and we should not change it.
All we need to know about the
main function is that it calls another function--
UIApplicationMain, which loads our UI, passes control to us for some initial setup if we wish to do so, and begins our main run loop via a
UIApplication object is responsible for handling communication between our code and Apple system frameworks.
UIApplciation object is a basic, built-in application. But at this point, there is no way for us to (safely) customize the code. The communication happens through a delegate on the application, namely, the app delegate. XCode projects come with an
AppDelegate class by default, so you don't have to worry about creating your own.
The app delegate is the standard delegate for built-in application object, it works with the
UIApplication object to handle application-level events like initialization and state transitions.
The app delegate creates a
UIWindow object as well as a view controller.
UIWindow is responsible for coordinating the presentation of one or more views on screen.
Most apps only have one window, which presents content on the main screen. The view controller is loaded inside of the
UIWindow object exists for the lifetime of the app. If you want to change the content on screen, you change view controllers— you'd never replace the window itself. It's responsiblities consist of delivering events to your views and view controllers.
As you can see, we don't touch much of the initial scaffolding of an iOS application. The only parts we consistently interact with are the app delegate and the view controllers. It's important to know where you are in the context of the application, because there are delegate methods that are called like
application:didFinishLaunchingWithOptions(_:) which is called in the app delegate for us to be able to react to application level events.
In our view controller, methods like
viewWillAppear: are also delegate methods called from the view life cycle, which you can see below.
If you've been developing iOS apps, you should be familiar with the MVC design pattern. If you aren't— MVC stands for Model, View, Controller. Briefly, the data model and the views should never directly communicate, rather, a View Controller should handle this communcation via communication patterns like delegation or KVO. You should definitely read up on it if you aren't familiar.
Interestingly enough, Apple's system frameworks are dependent on MVC and delegates for its implementation.
What's actually happening in that event loop though?
As a user interacts with a device, events related to those interactions are generated by the system and delivered to the app via a special port set up by
Events are queued internally by the app and dispatched one-by-one to the main run loop for execution.
UIApplication object is the first object to receive the event and make the decision about what needs to be done.
A touch event is usually dispatched to the main window object, which in turn dispatches it to the view in which the touch occured. Most events are delivered using the main run loop of your app.
It should be known that
IBActions that you set up with
UISegmentedControllers are not delivered using the main run loop. Touch events for these controls are delivered using target-actions-- which basically means that an object holds the information necessary to send a message to another object when an event occurs.
The most useful app delegate methods are those that correspond to execution state changes. When your app is running and your user gets a phone call, your app moves into the background, causing an execution state change. You'll have to use these delegate methods to react to these state changes with your app.