ios程序启动原理与窗口、控制加载、控制器view加载、导航控制器加载

来源:互联网 发布:mac照片和iphoto 编辑:程序博客网 时间:2024/06/10 05:55

一、程序启动过程
main —>UIApplicationMain
intmain(intargc, char * argv[])
{
   
@autoreleasepool{
       
returnUIApplicationMain(argc, argv,nil,NSStringFromClass([CXAppDelegateclass]));
    }
}
程序启动的入口,如果传入nil参数,默认为UIApplication类名字的字符串,可以用 NSStringFromClass([UIApplicationclass]) 和 @“UIApplication"来代替nil

UIApplicationMain底层的加载过程
1、创建UIApplication对象
2、创建UIApplicationDelegate对象,并且赋值给UIApplication对象的代理属性
3、开启主运行循环
4、加载into.plist文件,判断是否指定main.storyboard,如果指定,就去加载。

二、UIWindow
1、常见的窗口:键盘,UIActionSheet,UIAlertView
      特殊的窗口:状态栏
2、窗口的层级(windowLevel)
     UIWindowLevelNormal<UIWindowLevelStatusBar<UIWindowLevelAlert
     窗口默认都是UIWindowLevelNormal层级,键盘的层级永远是最高的,在显示之前会获取当前最高层级数,然后键盘的层级+1
     一个应用程序只能有一个主窗口
3、窗口中底层的实现方法
         // 1、创建窗口,创建的window需要用强指针来引用以避免刚创建就被销毁
    self.window = [[UIWindowalloc] initWithFrame:[UIScreen mainScreen].bounds];
    // 2、创建窗口的根控制器
    UIViewController *rootVc = [[UIViewControlleralloc]init];
    rootVc.view.backgroundColor = [UIColorredColor];
    // 3、把控制器作为窗口的根控制器
    // rootViewController的好处:1、可以让窗口旋转;2.让代码结构清晰(自定义跟控制器,控制器的事情写在控制器里面)
    window.rootViewController = rootVc;
         // 4、把窗口显示在屏幕上,并且成为应用程序的主窗口
    [window makeKeyAndVisible];
makeKeyAndVisible底层实现:
 1、成为application的主窗口 application.keyWindow = self.window;
 2、让窗口显示出来 self.window.hidden = NO;
 3、把窗口根控制器的view添加到窗口上  
  [self.window addSubview:window.rootViewController.view];


三、三种创建控制器的方法
1、直接创建
     UIViewController*vc = [[UIViewControlleralloc]init];

2、通过storyboard创建
      // 1.创建窗口
   self.window = [[UIWindowalloc] initWithFrame:[UIScreen mainScreen].bounds];

   // 2.1加载main.storyboard,并且实例化一个控制器
   UIStoryboard *storyboard = [UIStoryboardstoryboardWithName:@"Main"bundle:nil];

    // 2.2 实例化控制器instantiateInitialViewController:会去加载箭头指向的控制器)
    ViewController *vc = [storyboard instantiateInitialViewController];
    // ViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"vc"];
    // instantiateViewControllerWithIdentifier:会去storyboard中有木有vc这个标识的控制器
   
   
// 3.设置窗口的跟控制器
   
self.window.rootViewController= vc;
   
   
// 4.显示窗口
    [self.windowmakeKeyAndVisible];

3、通过xib文件创建
// 1、设置xibfile’owner的class属性为控制器Class
       2、加载xib需要file’owner和xib的view连线
self.window= [[UIWindowalloc]initWithFrame:[UIScreenmainScreen].bounds];
   
   
// Nib = xib
   
// 通过xib创建控制器
   
// 创建控制器,必须要有view,没有view就会报错
   
ViewController*vc = [[ViewControlleralloc]initWithNibName:@"VC"bundle:nil];
   
   
self.window.rootViewController= vc;
   
    [self.windowmakeKeyAndVisible];

四、控制器view的创建
1、loadView()
loadView作用:创建控制器的view
loadView什么时候去调用:第一次使用控制器的view的时候就会调用loadView
只要重写了loadView这个方法,就必须自己创建控制器的view,系统就不会帮你创建控制器view

2、loadView底层做法
0、判断控制器是否有重写loadView方法,如果有就只会加载loadView
1、判断下有没有指定storyboard,如果有,就去加载storyboard描述的控制器的view
2、判断下有没有指定nibName,如果有,就去加载nibName描述的控制器的view
     2.0如何判断有没有指定nibName,[self nibName]
     2.1判断下nibName是否为空,如果为空,他会尝试找下有没有跟控制器同名,但是不带Controller的xib
     2.2跟控制器同名的xib,nibName = ViewController,但是这一步有条件,前提条件你没有重写loadView
      CXViewController -> CXView.xib ->  CXViewController.xib
     2.3如果都没有找到,直接创建几乎透明的view(clear color)

[ViewControlleralloc]init]; 的底层会去调用 [ViewControlleralloc]initWithNibName:nilbundle:nil] 方法,从步骤2开始逐步执行判断

3、view为懒加载,当需要在屏幕上显示view的时候才会去调用loadView方法加载view
[[ViewControlleralloc]init].view.backgroundColor= [UIColorredColor];
当程序执行该代码时会先去判断view是否为空,如果不为空则直接返回已创建的view,如果为空,则会调用loadView方法加载view
/*********伪代码 *********/
- (UIView*)view
{
   
if (_view == nil) {
        [
self loadView];
        [
self viewDidLoad];
    }
   
return _view;
}
/*********伪代码 *********/
当view为空时,且重写了loadView方法并为view的背景赋值时

- (void)loadView
{
    // 因为重写了loadView方法,所以程序不会自动加载view,必须手动创建一个view给控制器
    self.view= [[UIViewalloc]initWithFrame:[UIScreenmainScreen].bounds];
   
   
self.view.backgroundColor= [UIColoryellowColor];
}

在viewDidLoad()方法里重新为控制器的view赋值,该方法会在控制器加载完所有的控件时候调用

- (void)viewDidLoad {
    [
super viewDidLoad];
   
self.view.backgroundColor= [UIColorblueColor];
   
   
NSLog(@"控制器的view加载完成了");
}

以上方法执行完,view的颜色将会是redColor

五、导航控制器

UINavigationController的view结构
导航控制器的view 在最底层,导航子控制器的view在第二层,导航条在最上面
当有控制器入栈时,控制器的view会添加到导航子控制器的view上

1、创建导航控制器必须要有一个导航控制器的根控制器,因为导航条的内容必须要依赖栈顶控制器,默认第一个根控制器就是栈顶控制器
    //创建导航控制器的跟控制器
    UIViewController *vc = [[ViewControlleralloc]init];
    vc.view.backgroundColor = [UIColorredColor];
    //创建导航控制器view,提示:导航控制器也需要一个跟控制器
    UINavigationController *nav = [[UINavigationControlleralloc] initWithRootViewController:vc];
    //导航控制器成为window的根控制器
    self.window.rootViewController= nav; 
    [self.windowmakeKeyAndVisible];
 2、initWithRootViewController:底层会调用pushViewController。
       pushViewController:底层会把控制器压入栈,并且把控制器的view添加到导航子控制器的view上面。
     如果导航子控制器上已有其他控制器的view,这时会推出其他控制器的view,并把自己的view添加上去(推出的view暂时不会被销毁,只有控制器出栈的时候才会销毁)

 3、等需要push控制器的view完全显示的时候,会拿到push控制的navigationController属性赋值导航控制器
    vc.navigationController = nav;
所以在被push的控制器里面可以访问到导航控制器
     self.navigationController
 4、导航控制器的viewControllers用来保存导航控制器里面所有的子控制器,让属性是个NSArray类型,0号索引永远是栈底
 5、导航控制器永远显示出来的界面是栈顶控制器的view
 6、 [self.navigationControllerpopViewControllerAnimated:YES];
调用这个方法,并不会马上出栈,等控制器的view完全移除父控件,才会出栈,控制器出栈后,就会被销毁

六、导航条的内容
1、导航条的内容由栈顶控制器的UINavigationItem决定,为什么要这样设计,因为导航控制器只有一个导航条,如果每个子控制器都能设置,就不知道听谁的了,所以由显示出来的控制器决定。
 2、UINavigationItem:是一个模型,用来决定导航条的内容。
 3、UIBarButtonItem:是一个模型,用来决定导航条上按钮的内容。
 4、导航条上面的子控件的位置由系统决定,但是尺寸是由我们自己决定
 4.1、[button sizeToFit]默认计算按钮尺寸,根据按钮的内容计算出最合适的尺寸
 5、在ios7之后,默认就会导航条上的按钮的图片渲染成蓝色
 5.1、如何保持图片最原始的效果,不要渲染
    [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
 5.2、Item就是模型,MVC,修改模型就能改界面

0 0
原创粉丝点击