首页 > 代码库 > iOS程序启动原理的理解

iOS程序启动原理的理解

应用的生命周期(从启动到退出):当用户点击应用图标之后,应用就开始启动。应用启动完成后,就会展示一系列的视图,和用户进行各种各样的交互(如滑动、点击)。当用户退出应用后,该应用就无法和用户进行交互。这一过程就是应用的生命周期体现

       在介绍应用启动过程及原理之前,先来了解一些概念以及其作用。

1、UIApplication

      UIApplication对象是应用程序的象征,一个UIApplication对象就代表一个应用程序。每一个应用都有自己的UIApplication对象,而且是单例的,如果试图在程序中新建一个UIApplication对象,那么将报错提示。一个iOS程序启动后创建的第一个对象就是UIApplication对象,且只有一个。利用UIApplication对象,能进行一些应用级别的操作。可以参考这篇文章

2、UIApplication Delegate

       所有的移动操作系统都有个致命的缺点:app很容易受到打扰。比如一个来电或者锁屏会导致app进入后台甚至被终止。还有很多其它类似的情况会导致app受到干扰,在app受到干扰时,会产生一些系统事件(iOS系统处理系统的事件的有限级别高于处理某个程序的事件),这时UIApplication会通知它的delegate对象,让delegate代理来处理这些系统事件

      所有UIApplicationDelegate的代理作用是当应用程序发出一系列系统事件时,做出相应的反应,也就是监听应用程序的状态变化如:进入、退出、程序间的调转。每次新建完项目,都有个带有“AppDelegate”字眼的类,它就是UIApplication的代理,AppDelegate默认已经遵守了UIApplicationDelegate协议,已经是UIApplication的代理。系统事件如程序降将要启动、程序启动完成、程序进入后台、程序进入前台、程序退出等。对应代理的方法如下:

 
  1. /** 
  2.  *  程序启动完成:各个类加载完毕
  3.  */  
  4. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
  5.     return YES;  
  6. }  
  7. /** 
  8.  *  程序将要进入后台:还没有进入后台的事件点,此时用户和界面还能够交互
  9.  */  
  10. - (void)applicationWillResignActive:(UIApplication *)application {  
  11. }  
  12.   
  13. /** 
  14.  *  程序进入后台 :直观的表现是用户不能界面交互
  15.  */  
  16. - (void)applicationDidEnterBackground:(UIApplication *)application {  
  17.   
  18. }  
  19.   
  20. /** 
  21.  *  程序将要进入前台 
  22.  */  
  23. - (void)applicationWillEnterForeground:(UIApplication *)application {  
  24.      
  25. }  
  26.   
  27. /** 
  28.  *  程序进入前台:获得的焦点,用户有能够与界面交互
  29.  */  
  30. - (void)applicationDidBecomeActive:(UIApplication *)application {  
  31.       
  32. }  
  33.   
  34. /** 
  35.  *  程序退出:
  36.  */  
  37. - (void)applicationWillTerminate:(UIApplication *)application {  
  38.       
  39. }  

       上面就是涉及到应用程序非常重要的两个概念,下面我们来介绍点击应用图标后,应用程序的启动。

,C语言是从main函数开始执行代码的。OC作为C语言的超集,当然也不例外。点击图标,开始执行main函数。iOS项目中的main函数是在创建项目的时候就已经写好了的,如下:

 

int main(int argc, char * argv[]) {

    @autoreleasepool {

        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

    }

}

 

  • UIApplicationMain函数参数

 

       可以看到ios项目中的main函数执行了一个UIApplicationMain函数,所有我们的重点就是要连接UIApplicationMain在执行的时候都做了哪些事情。下面我们先来了解一下UIApplicationMain函数的参数

  1. /** 
  2.  *  @param argc   系统参数 
  3.  *  @param argv   系统参数 
  4.  *  @param nil    应用程序名称 
  5.  *  @param class] 应用程序代理名称 
  6.  */  
  7. UIApplicationMain(int argc, charchar *argv[], NSString *principalClassName, NSString *delegateClassName);</span>  

 

argc、argv:直接传递给UIApplicationMain进行相关处理即可  

principalClassName:指定应用程序类名(app的象征),该类必须是UIApplication(或子类)。如果为nil,则用UIApplication类作为默认值

delegateClassName:指定应用程序的代理类,该类必须遵守UIApplicationDelegate协议:同过代理来监听各种程序各种状态的转变

  • UIApplicationMain函数作用

       main函数中之是执行了UIApplicationMain函数,可以肯定的时候该函数一定很重要,但它的具体作用是什么呢,

       UIApplicationMain函数会根据principalClassName创建UIApplication对象,根据delegateClassName创建一个delegate对象,并将该delegate对象赋值给UIApplication对象中的delegate属性 。

       接着会建立应用程序的Main Runloop(事件循环),进行事件的处理(首先会在程序完毕后调用delegate对象的application:didFinishLaunchingWithOptions:方法)。

       app启动时会加载Info.plist文件,看是否指定了main.storyboard,如果设置了就去加载main.storyboard,那么加载main.storyboard时,系统会进行如下操作:

       创建窗口 -> 加载main.storyboard并且加载main.storyboard中指定的控制器 -> 创建控制器成为窗口的根控制器,让窗口显示出来。

总结UIApplicationMain函数作用

argc:系统或者用户传入的参数 
argv:系统或用户传入的实际参数  
1.根据传入的第三个参数,创建UIApplication对象 
2.根据传入的第四个产生创建UIApplication对象的代理 
3.设置刚刚创建出来的代理对象为UIApplication的代理 
4.开启一个事件循环(可以理解为里面是一个死循环)这个时间循环是一个队列(先进先出)先添加进去的先处理
5.加载Info.plist文件,看是否指定了main.storyboard,如果设置了就去加载main.storyboard

3、UIWindow的创建

       UIWindow  是特殊的 UIView ,通常一个App中只有UIWindows,当程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的UIView,将控制器的View添加到UIWindow上,控制器的 UIView 就显示在屏幕上。注意 UIWindow 本身不做显示,是控制器的UIView做展示,UIWindow 会给视图分发事件。

       如果应用程序设置了main.storyboard文件,并指定了初始化控制器,系统会自动创建UIWindow。如果没有指定main.storyboard文件,就必须手动去创建。

UIWindow作用:

 

1.UIWindow作为一个容器,容纳所有的UIView

2.UIWindow会其他事件消息传递给UIWiew

4、控制器的创建

        当UIWindow创建完成后,必须指定一个根控制器或者在UIWIndow上添加子视图,这样才能显示出来,用户才能看得到,因为前面提到过,UIWindow本身不做显示。当指定了UIWindow的根控制器,该控制器的view会自动添加在UIWindow上,并显示出来。控制器的创建可以看这篇文章

5、视图控制器view的创建

       视图控制器就是控制器视图在屏幕上的显示,对于一个控制器来说也是不具备显示的,只有它的view才具有显示能力,所以创建完一个控制器的时候,要给它指定一个根视图。具体的控制器view的创建可以查看这篇文章。

6、应用程序的状态

应用程序到这里就可以显示了。根据前面的应用程序代理功能的介绍,应用程序在启动过程中有以下几种状态:

 

1. Not running :应用还没有启动,或者应用正在运行但是途中被系统停止。 

2. Inactive :当前应用正在前台运行,但是并不接收事件(当前 或许正在执行其它代码)。一般每当应用要从一个状态切换到另一个不同的状态时,中途过渡会短暂停留在此状态。唯一在此状态停留时间比较长的情况是:当用户 锁屏时,或者系统提示用户去响应某些(诸如电话来电、有未读短信等)事件的时候。

3. Active :当前应用正在前台运行,并且接收事件。这是应用正在前台运行时所处的正常状态。 

4. Background :应用处在后台,并且还在执行代码。大多数将 要进入Suspended状态的应用,会先短暂进入此状态。然而,对于请求需要额外的执行时间的应用,会在此状态保持更长一段时间。另外,如果一个应用要 求启动时直接进入后台运行,这样的应用会直接从Not running状态进入Background状态,中途不会经过Inactive状态。比如没有界面的应用。注此处并不特指没有界面的应用,其实也可以是 有界面的应用,只是如果要直接进入background状态的话,该应用界面不会被显示。

5. Suspended :应用处在后台,并且已停止执行代码。系统自动 的将应用移入此状态,且在此举之前不会对应用做任何通知。当处在此状态时,应用依然驻留内存但不执行任何程序代码。当系统发生低内存告警时,系统将会将处 于Suspended状态的应用清除出内存以为正在前台运行的应用提供足够的内存。

 

iOS程序启动原理的理解