walker代理深入浅出——IOS程序的启动原理(上)

  1. 每一个APP都是单例对象,其中有一个重要的info.plist文件,上面记录了程序的版本,identifier bundle等个人信息。非常重要
  2. 和C,OC一样,程序的启动入口都是main函数,只是此时的main函数比较特殊,是一个运行循环,不会释放,所以程序不会崩溃终止。一个程序就是进程,它里面可以有若干子线程。但所有关于UI的操作都放在主线程进行,主线程默认有一个运行循环,里面有两个重要的组成部分,分别为触摸事件循环和时间循环。可以接受UI界面的事件相应和计时操作。
  3. 每一个程序启动的时候,界面的显示都是由根控制器决定的。(涉及到如何显示界面View)
  4. 程序的生命周期 
 
 
正文:
     了解程序的启动原理,对IOS程序的理解有很大的帮助,实际很多抽象的概念,包括UI界面,多线程以及网络都和程序的启动原理有很大的关系。
     
     一个程序,在代码层就是一个UIApplication,而且是单例的,可以通过UIApplication SharedApplication来获取这个单例对象。
     如果把一个程序比作公司的话,UIApplication就是公司的CEO,类似于公司的成立之初,肯定有个创始人CEO。一个程序的启动运行,创建的第一个对象就是UIApplication。带有CEO属性的UIApplication会做一些应用层级的操作,至于程序的细节,会交给相对底层的其他人操作。
 

UIApplication的常用属性

1 // 设置应用程序图标右上角的红色提醒数字:
2 @property(nonatomic) NSInteger applicationIconBadgeNumber;
3 // 设置联网指示器(菊花)的可见性
4 @property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;

 

  另外,每一个应用程序不可能是孤立的,需要在应用程序之间做交互,或者打电话,打短信,打开网页等等高级的操作,这个时候,也需要这个CEO出马。那么UIApplication会调用相应的方法执行相关操作。
 
  UIApplication提供了一个功能强大的方法:openURL:
此时,这里的URL我们不要狭隘的理解成网址,它提供了丰富的方法:
  1.  1 //openURL:方法的部分功能有
     2 // 1>打电话
     3 UIApplication *app = [UIApplication sharedApplication];
     4 
     5 [app openURL:[NSURL URLWithString:@"tel://10086"]];
     6 
     7 // 2>发短信
     8 [app openURL:[NSURL URLWithString:@"sms://10086"]];
     9 
    10 // 3>发邮件
    11 [app openURL:[NSURL URLWithString:@"mailto://447640819@qq.com"]];
    12 
    13 // 4>打开一个网页资源
    14 [app openURL:[NSURL URLWithString:@"http://m.baidu.com"]];
    15 
    16 //  5>打开其他app程序

     

     但是CEO也有CEO的无奈,毕竟它只是自己程序的老大,它存在于系统之上,所以必须服从系统的安排。比如,来电话,锁屏,系统发来的内存警告等,CEO必须做出响应。但由于CEO的精力有限,所以找了秘书和部门主管来帮它响应系统事件。这些秘书和主管在应用程序中叫做“代理”即delegate,这些代理主要帮助UIApplication完成以下操作。

delegate可处理的事件包括:

    1> 应用程序的生命周期事件(如程序的启动和关闭);

    2> 系统事件(如来电);

    3> 内存警告...
但代理不能乱来,需要遵守协议,按照规则来执行,这个协议就是UIApplicationDelegate;

UIApplicationDelegate协议

1 // app接收到内存警告时调用
2 - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;
3 // app进入后台时调用(比如按了home键)
4 - (void)applicationDidEnterBackground:(UIApplication *)application;
5 // app启动完毕时调用
6 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

 

    每次新建完项目,系统默认会创建一个AppDelegate,这个代理默认遵守了UIApplicationDelegate.
@interface AppDelegate : UIResponder <UIApplicationDelegate>
 
   在不同代理协议中,可自己定义相应的方法,完成响应。
 
    
 
程序的加载过程:
  1. 程序加载完毕
  2. 程序获取焦点
  3. 程序进入后台
  4. 程序失去焦点
  5. 程序从后台进入前台
  6. 内存警告,可能终止程序
  7. 程序即将退出
 

main函数中执行了一个UIApplicationMain这个函数.

1 int main(int argc, char * argv[])
2 {
3     @autoreleasepool {
4         return UIApplicationMain(argc, argv, nil, NSStringFromClass([JNAppDelegate class]));
5     }
6 }
7 
8 
9 int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);

   每个参数的意义如下:

  • argc:系统或者用户传入的参数个数(根据int判断是个数)
  • argv:系统或者用户传入的实际参数(根据char判断是实际参数)
  • principalClassName:指定APP的类名(APP的象征),此类必须是UIApplication或其子类。可以直接为nil,此时默认为UIApplication.
  • delegateClassName:指定APP的代理类,这个类必须遵守UIApplicationDelegate协议
 
  上述都创建完成后,会设置代理对象为UIApplication的代理,然后开启一个事件循环Main Runloop(可以理解一个死循环,里面是一个队列,所有的任务遵守“先进先出”的原则,随放在前面,随优先执行,其他顺次执行.首先会在程序启动完毕后调用delegate对象的application:didFinishLaunchingWithOptions:方法)
 
     想象一下,在公司创建的时候,会根据供公司章程,产生一个CEO,并且根据公司业务创建一个代理(帮助CEO干活的秘书和主管)。
     同样作为程序本身,在程序启动的时候,UIApplicationMain函数(类似于公司章程)会根据principalClassName创建一个UIApplication对象,根据delegateClassName创建一个代理对象,并且把该对象赋值给UIApplication对象中的delegate属性。
同样作为公司,为了保证公司持续运作,必须保证公司员工有持续的收入,公司每个月都不断有收入,不会断片。
     同样,回到函数本身,在函数内部,肯定不能在main内部执行一次就释放掉了。函数是保证程序运行的根本,是程序的开头。main执行完成释放掉,意味着程序也崩溃了。所以为了保证程序的不断运行,在main函数的内部创建了一个Main Runloop(事件循环),进行时间的处理(首先在程序完毕后调用delegate对象的application:didFinishLauchingWithOptions:方法),程序正常退出的时候,Main Runloop才返回。
 
     所以综述整个程序启动的完整过程为:
  1. 开启main函数,根据UIApplicationMain,完成创建UIApplication和设置UIApplication的delegate等一系列操作。
  2. 代理对象开始监听系统事件(没有storyboard),执行application:didFinishLaunchingWithOptions:并在该方法内部创建UIWindow和rootViewController,然后设置可见,并显示窗口。
  3. 根据info.plist文件获得storyboard的文件名,(如果有storyboard),就加载storyboard。
 
用公司来类别的话,就更容易理解。
  1. 创建公司,根据公司章程选举CEO,秘书和部门主管。完成领导班子的组件。
  2. 然后公司展开业务时,必须向外展示公司的业务(UIWindow创建),然后确定公司的根本业务(rootViewController)开展业务。(当然公司会有副业,会创建新的控制器,交由该控制器管理)。
  3. storyboard类似公司的子公司。(它里面有丰富的组成元素,但可有可无,未必必须存在。)
 
     程序的启动原理会在下一个博客中深入讲解。
 
 
 
posted @ 2016-02-21 21:08  walker彬  阅读(158)  评论(0编辑  收藏  举报