iOS程序启动的完整过程和控制器与视图的生命周期详解

前言:

    这部分内容,对于大部分人来说使用起来可能已经非常熟练,但是涉及到的细节还是挺多的,对于新开发者可能不是很明白,没有一个整体的思路,此文旨在帮助入门者整理一下,顺便自己也加深一下印象,只有理解了这些过程与方法,才能更好的写代码,让我们的应用程序设计更合理。其中有些问题也是面试经常被问到的一个问题,希望能帮助到大家。谢谢。

一:UIWindow对象

         UIWindow是一种特殊的UIView, 继承自UIView。通常一个app只会有一个UIWindow对象,iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器和控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了,一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow

二:应用程序的启动过程

创建过程UIWindow -> UIViewController -> UIView ->把UIView加到UIWindow对象中。

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

             nil:设置启动UIApplication对象,

             NSStringFromClass([AppDelegate class]):设置代理对象AppDelegate。 并且将AppDelegate代理对象设置给UIApplication对象 最后创建事件循环

1.>.调用main函数。

2.>在main函数中调用UIApplicationMain函数。

3.>在UIApplicationMain()函数中:

      (1)创建UIApplication对象、AppDelegate对象

      (2)设置UIApplicatio对象的代理是AppDelegate对象。

      (3) AppDelegate对象开始监听"系统事件(应用程序的事件)",进入"事件循环"。

      (4)程序启动完毕后调用application:didFinishLaunchingWithOptions:方法。,

2.1:在应用程序的启动过程中,窗口必须有根控制器,控制器必须有视图,这样视图才能显示给用户,

控制器UIViewController的创建方式:

          2.1.1:代码创建

完成前面工作后,在此方法中:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

//创建UIWindow对象

self.window=[[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

//创建窗口的根控制器

UIViewController *rootVC=[[UIViewController alloc] init];

//设置根控制器视图的背景颜色

rootVC.view.backgroundColor=[UIColor redColor];

//把创建的控制器作为窗口的根控制器

self.window.rootViewController=rootVC;

//让窗口显示在屏幕上

[self.window makeKeyAndVisible];

return YES;

}

注意:如果窗口没有根控制器会报错

reason: 'Application windows are expected to have a root view controller at the end of application launch'

          2.1.2:加载storyboard文件

完成前面工作后,在此方法中:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

1://通过系统提供的Main.storyboard,此过程由系统完成

*系统自动创建UIWindow对象。

*根据Info.plist文件配置(Main Interface),找到需要加载的storyboard文件(Main.storyboard)

*找到Main.storyboard中的Is Initial View Controller对应的控制器类,创建该控制器对象,并创建该控制器对应的view。

*设置UIWindow的根控制器(rootViewController)为刚才创建的控制器。

*显示UIWindow([self.window makeKeyAndVisible])。


2://通过代码,加载自己创建的My.storyboard文件创建

//创建窗口

self.window= [[UIWindow alloc] initWithFrame:[UIScreenmainScreen].bounds];

//创建UIStoryboard对象  Name:传storyboard的文件名,不需要带后缀

UIStoryboard*storyboard = [UIStoryboard storyboardWithName:@"My"bundle:nil];

// 实例化一个控制器 

第一种:创建箭头指向的控制器、如果有勾选了iS Initial View Controller的控制器

UIViewController*vc = [storyboard instantiateInitialViewController];

第二种;创建有标示符的控制器,当storyboard文件中有多个控制器的时候使用,需要设置此控制器的Storyboard ID 为''vc'', 此方法会覆盖上面的方法。

UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"vc"];

// 设置窗口的跟控制器

self.window.rootViewController= vc;

// 让窗口显示出来并且成为主窗口

[self.windowmakeKeyAndVisible];

return YES;

视图UIView的创建方式

       视图控制器创建好之后,就会创建控制器的视图View,控制器view是懒加载的过程,也就是说,在需要的时候(在用到的时候)才会创建(调用loadView方法),在控制器view的加载过程中,系统底层会调用View的get方法,这个get方法内部会调用这个loadView和viewDidLoad的方法,只要控制器的loadView方法被调用了,当调用完毕控制器的loadView方法以后,那么证明控制器的View创建好了,当控制器的View被创建好以后,紧接着就调用控制器的viewDidLoad方法。

注意:无论控制器是如何创建的,只要在控制器中,重写了("实现了")loadView方法,并且没有调用[super loadView]方法,那么最终控制器的View就必须完全在loadView方法中自己来创建了。所以loadView方法可以用来自定义View。

1>通过storyboard创建的控制器,系统会帮我们加载对应控制器所描述的view,

2>通过Xib创建控制器的view

如果没有重写loadView方法  底层实现方式

(1)创建一个xib文件,

(2)自定义一个控制器ViewController,

(3)告诉这个xib是用来描述哪个控制器,设置文件拥有者,设置file‘s.Owner的class为ViewController,就可以连线,然后连线 右键file‘s.Owner把view连到xib文件的view上

(4)在此方法中

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {

self.window= [[UIWindowalloc]initWithFrame:[UIScreenmainScreen].bounds];

//通过Xib创建控制器的view  Nib:xib名称

self.window.rootViewController= [[ViewController alloc] initWithNibName:@"My"bundle:nil];

[self.windowmakeKeyAndVisible];

returnYES;

}

通过xib创建控制器view的加载顺序

      当用xib创建控制器view的时候,如果写了name名称,就加载和name相同的xib,如My.xib ,不写xib名称会默认加载和控制器同名的xib,如:ViewController.xib  如果没有和控制器同名的xib,就加载和控制器同名但是去掉Controller的xib,如:View.xib,   如果都没有找到,直接创建默认控制器的View, 默认控制器的View的颜色是几乎透明的clearcolor


3>自定义

如果在控制器中重写了loadView方法  一般在此方法中自定义view

- (void)loadView

{

// [super loadView]; 调用了[super loadView],那么依然会使用默认的方式来加载。所以自定义view不需要写。

self.view = [[UIView alloc] init];

self.view.backgroundColor = [UIColor purpleColor];

}

三:控制器和视图的生命周期

生命周期的方法及调用顺序

init:初始化

loadView: 加载view

viewDidLoad: view加载完毕

viewWillAppear: 控制器的view将要显示

viewWillLayoutSubviews: 控制器的view将要布局子控件

viewDidLayoutSubviews: 控制器的view布局子控件完成

viewDidAppear: 控制器的view完全显示

viewWillDisappear: 控制器的view即将消失的时候

viewDidDisappear: 控制器的view完全消失的时候


四:一些方法说明

LoadView:

这个方法的默认实现是这样:先寻找有关可用的nib文件的信息,根据这个信息来加载nib文件,如果没有有关nib文件的信息,默认实现会创建一个空白的UIView对象,然后让这个对象成为controller的主view。

每次访问UIViewController的view(比如controller.view、self.view)而且view为nil,loadView方法就会被调用。loadView方法是用来负责创建UIViewController的view,当需要自定义view的时候我们可以重写这个方法 但是不要实现[super loadView],要不然还是按照系统默认的方式创建,你只需要在 loadView 时创建 view,不要对它做什么自定义的,

viewDidLoad

不管你是通过xib文件还是重写loadView创建UIViewController的view,在view创建完毕后,最终都会调用viewDidLoad方法,

一般我们会在这里做界面上的初始化操作,比如往view中添加一些子视图、从数据库或者网络加载模型数据装配到子视图中

awakeFromNib

当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的awakeFromNib函数来响应这个消息,执行一些必要的操作。也就是说通过nib文件创建view对象时执行awakeFromNib。当一个对象从xib或者storyboard中加载完毕后,就会调用一次

initWithCoder

从文件中解析一个对象的时候就会调用这个方法,一个类在IB中创建但在xocdde中被实例化时被调用的.比如,通过IB创建一个controller的nib文件,然后在xocde中通过initWithNibName来实例化这个controller,那么这个controller的initWithCoder会被调用。

由于此部分内容细节比较多,本人也只能想到这么多,如有不正确的地方,希望大神指正一下,共同进步。谢谢。。。

   

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容