The App Launch Cycle

When your app is launched, it moves from the not running state to the active or background state, transitioning briefly through the inactive state.(当应用launch时,它由不运行状态简短经过不活动状态转换成活动状态或者后台状态。) As part of the launch cycle, the system creates a process and main thread for your app and calls your app’s main function on that main thread. The default main function that comes with your Xcode project promptly hands control over to the UIKit framework, which does most of the work in initializing your app and preparing it to run.(作为应用登陆的一部分,系统创建进程,主线程,调用main 线程里的main方法,默认的main迅速将控制权递交给uikit框架。uikit框架做了大多数的应用初始化工作,准备运行工作)

Figure 3-2 shows the sequence of events that occurs when an app is launched into the foreground, including the app delegate methods that are called.

Figure 3-2  Launching an app into the foregroundApplication life cycle

If your app is launched into the background instead(如果应用直接登陆到后台状态)—usually to handle some type of background event—the launch cycle changes slightly to the one shown in Figure 3-3. The main difference is that instead of your app being made active, it enters the background state to handle the event and then is suspended shortly afterward. When launching into the background, the system still loads your app’s user interface files but it does not display the app’s window.(当登陆到后台,系统仍然加载用户界面的接口文件,但是不显示应用的窗口)

Figure 3-3  Launching an app into the background

To determine whether your app is launching into the foreground or background, check the applicationStateproperty of the shared UIApplication object in your application:willFinishLaunchingWithOptions: orapplication:didFinishLaunchingWithOptions: delegate method. (通过查看在代理方法里的UIApplication object 的applicationState属性,来决定应用将要进入前台还是后台,如果进入前台属性是UIApplicationStateInactive,如果进入后台,这个属性值是:UIApplicationStateBackground)When the app is launched into the foreground, this property contains the value UIApplicationStateInactive. When the app is launched into the background, the property contains the value UIApplicationStateBackground instead. You can use this difference to adjust the launch-time behavior of your delegate methods accordingly.(可以根据这个区别来分别调整代理方法的登陆时行为)

Note: When an app is launched so that it can open a URL, the sequence of startup events is slightly different from those shown in Figure 3-2 and Figure 3-3. For information about the startup sequences that occur when opening a URL, see “Handling URL Requests.”

About the main Function

Like any C-based app, the main entry point for an iOS app at launch time is the main function. In an iOS app, themain function is used only minimally. Its main job is to hand control to the UIKit framework. Therefore, any new project you create in Xcode comes with a default main function like the one shown in Listing 3-1. With few exceptions, you should never change the implementation of this function.

Listing 3-1  The main function of an iOS app

#import <UIKit/UIKit.h>
 
int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}
 

The UIApplicationMain function takes four parameters and uses them to initialize the app. You should never have to change the default values passed into this function. Still, it is valuable to understand their purpose and how they start the app.

  • The argc and argv parameters contain any launch-time arguments passed to the app from the system. These arguments are parsed by the UIKit infrastructure and can otherwise be ignored.

  • The third parameter identifies the name of the principal app class. This is the class responsible for running the app. It is recommend that you specify nil for this parameter, which causes UIKit to use the UIApplicationclass.

  • The fourth parameter identifies the class of your custom app delegate. Your app delegate is responsible for managing the high-level interactions between the system and your code. The Xcode template projects set this parameter to an appropriate value automatically.

Another thing the UIApplicationMain function does is load the app’s main user interface file. (加载应用主接口文件)The main interface file contains the initial view-related objects you plan to display in your app’s user interface. For apps that useuse storyboards, this function loads the initial view controller from your storyboard and installs it in the window provided by your app delegate.(如果应用用storyboards,UIApplicationMain函数负责从storyboard加载初始view controller,并把它安装在delegate的window中) For apps that use nib files, the function loads the nib file contents into memory but does not install them in your app’s window; you must install them in theapplication:willFinishLaunchingWithOptions: method of your app delegate.(对于使用nib,这个函数只负责将nib文件加载到内存,并不将它们安装到app的窗口中,你必须在代理方法中安装这些nib);

An app can have either a main storyboard file or a main nib file but it cannot have both. Storyboards are the preferred way to specify your app’s user interface but are not supported on all versions of iOS. The name of your app’s main storyboard file goes in the UIMainStoryboardFile key of your app’s Info.plist file. (For nib-based apps, the name of your main nib file goes in the NSMainNibFile key instead.) Normally, Xcode sets the value of the appropriate key when you create your project, but you can change it later if needed.(应用不能即有storyboard又有nib.  推荐storyboard,但是它并不支持所有版本。应用主storyboard名是info.plist文件UIMainStoryboardFile这个key的值。)

For more information about the Info.plist file and how you use it to configure your app, see “The Information Property List File.”

What to Do at Launch Time

When your app is launched (either into the foreground or background), use your app delegate’sapplication:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions:methods to do the following:

  • Check the contents of the launch options dictionary for information about why the app was launched, and respond appropriately.(check登陆选项字典里的内容关于应用为什么登陆,并做正确响应)

  • Initialize the app’s critical data structures.(初始化应用关键数据结构)

  • Prepare your app’s window and views for display.(准备应用的窗口和试图)

    Apps that use OpenGL ES should not use this method to prepare their drawing environment. Instead, they should defer any OpenGL ES drawing calls to the applicationDidBecomeActive: method.(opengl es应该用... becomeActive方法来准备绘图环境)

If your app does not automatically load a main storyboard or nib file at launch time, you can use theapplication:willFinishLaunchingWithOptions: method to prepare your app’s window for display. (如果应用不加载主storyboard or nib文件,你用这个方法来准备应用的窗口)For apps that support both portrait and landscape orientations, always set up the root view controller of your main window in a portrait orientation. (对于支持横竖屏的应用,总要设定主窗口的根试图控制器为竖方向)If the device is in a different orientation at launch time, the system tells the root view controller to rotate your views to the correct orientation before displaying the window.(app登陆时,如果设备处于不同方向时,系统在显示窗口前会告诉根试图控制器去旋转你的试图到正确方向)

Your application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions:methods should always be as lightweight as possible to reduce your app’s launch time.(这两个方法应该时轻量级的来减少应用登陆的时间) Apps are expected to launch and initialize themselves and start handling events in less than 5 seconds. (在5秒内应用要能完成登陆,初始化完成,并开始能响应事件)If an app does not finish its launch cycle in a timely manner, the system kills it for being unresponsive. (如果超了,系统会因为不响应而杀死它)Thus, any tasks that might slow down your launch (such as accessing the network) should be executed asynchronously on a secondary thread.(所以请求网络的耗时任务应该开辟辅助线程来完成)

When launching into the foreground, the system also calls the applicationDidBecomeActive: method to finish the transition to the foreground. Because this method is called both at launch time and when transitioning from the background(这个方法在应用登陆和从后台转换过来的时候都会调用), use it to perform any tasks that are common to the two transitions.(把都执行都任务写这里)

When launching into the background, there should not be much for your app to do except get ready to handle whatever event arrived.(如果app 登陆到后台,应用不需要做太多,除非准备处理各种发生的事件)

Responding to Interruptions

When an alert-based interruption occurs, such as an incoming phone call, the app moves temporarily to the inactive state so that the system can prompt the user about how to proceed. (如果进来电话了,应用临时转换到inactive状态以便系统能提示用户怎么处理,一直到用户消除这个提示)The app remains in this state until the user dismisses the alert. At this point, the app either returns to the active state or moves to the background state.Figure 3-4 shows the flow of events through your app when an alert-based interruption occurs.(此时,应用或者进入active状态,或者进入到后台状态)

Figure 3-4  Handling alert-based interruptions

In iOS 5, notifications that display a banner do not deactivate your app in the way that alert-based notifications do. Instead, the banner is laid along the top edge of your app window and your app continues receive touch events as before. However, if the user pulls down the banner to reveal the notification center, your app moves to the inactive state just as if an alert-based interruption had occurred. Your app remains in the inactive state until the user dismisses the notification center or launches another app. At this point, your app moves to the appropriate active or background state. The user can use the Settings app to configure which notifications display a banner and which display an alert.(ios5 通知显示为banner,并不像基于alert通知做的那样让你应用不能用了,banner躺在你应用窗口顶端的边上,你的应用像之前一样可以接收事件。然而当你下拉banner查看通知中心,你的应用进入到不活跃状态。 你退出notification 中心或者登陆其它应用,你的应用相应地进入活跃状态,或者后台状态。用户可以设定哪些通知显示为banner,哪些显示为alert)

Pressing the Sleep/Wake button is another type of interruption that causes your app to be deactivated temporarily. When the user presses this button, the system disables touch events, moves the app to the background but sets the value of the app’s applicationState property to UIApplicationStateInactive (as opposed toUIApplicationStateBackground), and finally locks the screen. (按Sleep/wake键是另一种使你的应用临时不活动的中断,当用户按这个键时,系统禁止了触摸事件,把应用移动到后台,但是设置应用的状态值为inactive,而不是backgroud;最后锁定了屏幕)A locked screen has additional consequences for apps that use data protection to encrypt files. Those consequences are described in “What to Do When an Interruption Occurs.”

What to Do When an Interruption Occurs

Alert-based interruptions result in a temporary loss of control by your app. Your app continues to run in the foreground, but it does not receive touch events from the system. (It does continue to receive notifications and other types of events, such as accelerometer events, though.) In response to this change, your app should do the following in its applicationWillResignActive: method:(当中断发生,应用仍然在前台运行,但是不能接收触摸事件,应该在willresignactive里进行如下操作)

  • Stop timers and other periodic tasks.--停止定时器,其它周期任务

  • Stop any running metadata queries. --停止任何数据查询

  • Do not initiate any new tasks. --不产生任何新任务

  • Pause movie playback (except when playing back over AirPlay). -- 暂停movie播放

  • Enter into a pause state if your app is a game.(游戏暂停)

  • Throttle back OpenGL ES frame rates. (降低opengl es 帧律)

  • Suspend any dispatch queues or operation queues executing non-critical code. (You can continue processing network requests and other time-sensitive background tasks while inactive.) --挂起非关键代码的dispatch,operation队列

When your app is moved back to the active state, its applicationDidBecomeActive: method should reverse any of the steps taken in the applicationWillResignActive: method. Thus, upon reactivation, your app should restart timers, resume dispatch queues, and throttle up OpenGL ES frame rates again. However, games should not resume automatically; they should remain paused until the user chooses to resume them(如果进如活动状态,需要在该方法中执行上述相反的动作,但是游戏还要暂停,让用户重新启动)

When the user presses the Sleep/Wake button, apps with files protected by the NSFileProtectionCompleteprotection option must close any references to those files. For devices configured with an appropriate password, pressing the Sleep/Wake button locks the screen and forces the system to throw away the decryption keys for files with complete protection enabled. While the screen is locked, any attempts to access the corresponding files will fail. So if you have such files, you should close any references to them in your applicationWillResignActive:method and open new references in your applicationDidBecomeActive: method.

Adjusting Your User Interface During a Phone Call

When the user takes a call and then returns to your app while on the call, the height of the status bar grows to reflect the fact that the user is on a call. Similarly, when the user ends the call, the status bar height shrinks back to its regular size.

The best way to handle status bar height changes is to use view controllers to manage your views. When installed in your interface, view controllers automatically adjust the height of their managed views when the status bar frame size changes.

If your app does not use view controllers for some reason, you must respond to status bar frame changes manually by registering for the UIApplicationDidChangeStatusBarFrameNotification notification. Your handler for this notification should get the status bar height and use it to adjust the height of your app’s views appropriately.(如果没用viewcontroller,就应该注册这个通知,接到通知,取得状态条高度,用这个高度调整应用视图的高度)

Moving to the Background

When the user presses the Home button, presses the Sleep/Wake button, or the system launches another app, the foreground app transitions to the inactive state and then to the background state. These transitions result in calls to the app delegate’s applicationWillResignActive: and applicationDidEnterBackground: methods, as shown in Figure 3-5. After returning from the applicationDidEnterBackground: method, most apps move to the suspended state shortly afterward. Apps that request specific background tasks (such as playing music) or that request a little extra execution time from the system may continue to run for a while longer.

当用户按home键,sleep/wake键 或者系统登陆另一个app,前台应用转换到不活动状态然后进入到后台状态。这些转换导致应用代理的两个方法调用。从applicationDidEnterBackground:返回之后,大多数应用很快进入到挂起状态。请求特定后台任务或者请求一些额外执行时间的应用可能继续执行更长一段

Figure 3-5  Moving from the foreground to the background

Note: Apps are moved to the background only on devices that support multitasking and only if those devices are running iOS 4.0 or later. In all other cases, the app is terminated (and thus purged from memory) instead of moved to the background.(只有支持多任务的设备,以及使用iOS4.0或者之后系统的设备才会移动到后台,在其它情况下应用会被终止,清理出内存而不是移动到后台)

What to Do When Moving to the Background

Apps can use their applicationDidEnterBackground: method to prepare for moving to the background state. When moving to the background, all apps should do the following:

  • Prepare to have their picture taken. When the applicationDidEnterBackground: method returns, the system takes a picture of your app’s user interface and uses the resulting image for transition animations. If any views in your interface contain sensitive information, you should hide or modify those views before theapplicationDidEnterBackground: method returns.(产生快照用作切换的动画)

  • Save user data and app state information. All unsaved changes should be written to disk when entering the background. This step is necessary because your app might be quietly killed while in the background for any number of reasons. You can perform this operation from a background thread as needed.(存储用户数据和应用状态信息,这步很重要,因为应用很有可能被悄悄杀死。可以用后台线程执行这个操作)

  • Free up as much memory as possible. For more information about what to do and why this is important, see“Memory Usage for Background Apps.”

Your app delegate’s applicationDidEnterBackground: method has approximately 5 seconds to finish any tasks and return. In practice, this method should return as quickly as possible. If the method does not return before time runs out, your app is killed and purged from memory. If you still need more time to perform tasks, call thebeginBackgroundTaskWithExpirationHandler: method to request background execution time and then start any long-running tasks in a secondary thread. Regardless of whether you start any background tasks, theapplicationDidEnterBackground: method must still exit within 5 seconds.(5秒钟,如果未执行完,应用将被杀死。可以调用beginBackgroundTaskWithExpirationHandler:方法请求后台执行时间然后在辅助进程中启动人异常时间的任务。无论是否启动后台任务,applicationDidEnterBackground:一定要5秒内返回

Note: The UIApplicationDidEnterBackgroundNotification notification is also sent to let interested parts of your app know that it is entering the background. Objects in your app can use the default notification center to register for this notification.

 (UIApplicationDidEnterBackgroundNotification)这个通知也被传递给应用的其它部分。应用里的对象可以向默认通知中心注册接收这个通知。

Depending on the features of your app, there are other things your app should do when moving to the background. For example, any active Bonjour services should be suspended and the app should stop calling OpenGL ES functions. For a list of things your app should do when moving to the background, see “Being a Responsible Background App.”

Memory Usage for Background Apps

Every app should free up as much memory as is practical upon entering the background. The system tries to keep as many apps in memory at the same time as it can, but when memory runs low it terminates suspended apps to reclaim that memory. Apps that consume large amounts of memory while in the background are the first apps to be terminated.(后台大内存的先被系统干掉)

Practically speaking, your app should remove strong references to objects as soon as they are no longer needed. (如果不再需要,你的应用应该移除对象的强引用,移除强引用给编译器机会去立刻释放对象,所占用内存可被再使用)Removing strong references gives the compiler the ability to release the objects right away so that the corresponding memory can be reclaimed. However, if you want to cache some objects to improve performance, you can wait until the app transitions to the background before removing references to them.(但是如果你想缓存一些对象来改善性能,你可以等到应用转换到后台再移除这些对象的强引用)

Some examples of objects that you should remove strong references to as soon as possible include:(最好立刻移除强引用的地方)

  • Image objects (图片对象)

  • Large media or data files that you can load again from disk (可以再次从磁盘加载的大的媒体或者数据文件)

  • Any other objects that your app does not need and can recreate easily later(任何应用不需要并且之后可以很容易再创建的对象)

To help reduce your app’s memory footprint, the system automatically purges some data allocated on behalf of your app when your app moves to the background.

  • The system purges the backing store for all Core Animation layers. This effort does not remove your app’s layer objects from memory, nor does it change the current layer properties. It simply prevents the contents of those layers from appearing onscreen, which given that the app is in the background should not happen anyway.

  • It removes any system references to cached images. (If your app does not have a strong reference to the images, they are subsequently removed from memory.)

  • It removes strong references to some other system-managed data caches.

原文地址:https://www.cnblogs.com/cocoabanana/p/3691855.html