3.UIViewController详解

 一. UIViewController,视图控制器,它是UIKit中非常重要的组成部分。它由控制器+View两部分组成。 

     控制器功能:

      -》实现代码逻辑,决定它自带的View的界面显示。

      -》控制器与控制器之间的通信,如传值,跳转。

      -》以及与Model和View间的信息传递。

      -》可以通过addChirldViewController来添加子控制器。(如抽屉效果,多选tableView都是采用此方式)

     视图功能:

      -》向用户展示信息

      -》可以添加子视图,设置子视图的层别

      -》可以接收响应事件(用户在触摸后屏幕后就会形成一个基于触摸点的UIEvent事件)

       这个事件通过 application - > keyWindow- > UIViewController(可选择,如果没有则直接传递给下一级)-》View-》subView -》.....->知道最终找到触摸点所在的那个位置对应的视图->查找该处视图是否有添加响应时间-》没有则自动释放-》有则通过该触摸点View->父视图-》控制器(没有直接向上一级出传递)-》keyWindow-》applcation。

二. UIViewController的生命周期

    经过测试执行顺序由上到下:

    1. 首先给视图控制器分配空间,然后初试化,接着创建唯一的UIView视图。

     2016-03-10 22:24:47.029 Demo_10_抽屉效果[74967:4603110] +[MainViewController alloc],分配空间

    2. init方法初始化,将这块内存的数据清空;系统也提供了init的改写方法,在初试化的时候直接连View一起加载好,

       视图控制器初试化好之后就是加载VIew,加载View有三种方式.

      -> 通过initWithCoder:从故事版中加载

      -> 通过initWithNibName:从xib中加载

      -> 通过自己使用代码进行创建。

       在没有故事版和storyBoard调用次方法视图可以从Xib  StroyBoard 代码中创建

   2016-03-10 22:24:47.029 Demo_10_抽屉效果[74967:4603110] -[MainViewController initWithCoder:],从故事板归档文件中加载视图出来了 

   - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 从xib二进制文件中加载出来了

      将解压或者代码创建视图加载出来

   3. loadView,将从storyBoard或者Nib文件,或者代码创建的View加载到系统中

  2016-03-10 22:24:47.061 Demo_10_抽屉效果[74967:4603110] -[MainViewController loadView],加载控制器的唯一视图View视图已经加载出来了

   4. View已经加载出来了,如果改视图控制器不销毁,只是界面切换,那么此方法只会执行一次。

 2016-03-10 22:24:47.062 Demo_10_抽屉效果[74967:4603110] -[MainViewController viewDidLoad],视图已经加载出来了  视图将要显示在手机屏幕上

   5. View将要显示到屏幕上,通常我们需要进行一些预先加载的操作可以写到这里,比如添加通知事件。

 2016-03-10 22:24:47.063 Demo_10_抽屉效果[74967:4603110] -[MainViewController viewWillAppear:],视图将要显示在屏幕界面上了

   6. 因为ViewFrame已经计算好了,且将要显示到屏幕上,但是它的子视图还没有固定好,所有先要调用子视图的两个方法

        视图开始布局子视图了,当子视图的约束写在此方法中时,当视图变化时候,子视图会跟着变化。

  2016-03-10 22:24:47.069 Demo_10_抽屉效果[74967:4603110] -[MainViewController viewWillLayoutSubviews],视图开始布局自视图了

    . 2016-03-10 22:24:47.069 Demo_10_抽屉效果[74967:4603110] -[MainViewController viewDidLayoutSubviews],视图的子视图已经布局完了

   7.  subView布局好之后,View才开始真正的显示视图

       [MainViewController viewDidAppear:],视图已经出现在屏幕上了

   8.  View将要消失

      -(void)viewWillDisappear:(BOOL)animated

   9. View已经消失在界面上了。通常我们一些通知事件移除可以写在此方法中。

      - (void)viewDidDisappear:(BOOL)animated

   10.控制器收到了内存不足警告

      - (void)didReceiveMemoryWarning

   11.下面两个是死亡方法

      - (void)viewDidUnLoad 视图警告内存不足可能被卸掉,下次就会继续执行viewDidLoad

      - (void)dealloc 当前视图控制器销毁

三 . UIViewController中布局子视图的时机。

     通常我们所说的布局子视图其实就是调用layOutSubViews.应为只有这个方法才会对父视图上的所有子视图进行统一的计算,然后再进行调用。

     下面请看这几个方法:

      1. layOutSubViews: 这个方法默认是什么都不做的,我们需要布局的子视图对象的frame计算方式都可以写在这里。

      2. setNeedsLayout方法:将调用者标记为需要进行重新布局,采取异步调用layoutIfNeed刷行布局(异步及另外开辟线程,不会立即刷新)。同时会调用layOutSubViews的方式刷新子视图布局。 

      3.layoutIfNeeded方法:如果该对象有需要刷新的标记,则会立即自动调用layoutSubViews。(如果没有这个标记的话,则不会马上调用layOutSubViews);视图在第一次看时的时候都会有需要刷新的标记,所以可以调用  [xxx.view layOutIfNeeded]

      4. 子视图重绘改变布局:

          -drawRect:(CGRect)rect方法:重写此方法执行重绘任务。

          -setNeedsDisplay方法,标记为需要绘,异步执行上面的方法进行绘制。例如当我们在做画笔工具的时候需要对路径进行实时勾勒,可以调用此方法。

           -setNessdsDisplayInRect:(CGRect)invalidRect方法:标记为需要局部重绘。

#pragma mark NSObject 线程安全与运行环境加载
+ (void)load {
    NSLog(@"%s",__func__);
}

+ (void)initialize {
        NSLog(@"%s",__func__);
}

+ (instancetype)alloc {
        NSLog(@"%s,分配空间",__func__);
    return  [super alloc];
}

//+ (instancetype)allocWithZone:(struct _NSZone *)zone {
//        NSLog(@"%s,分配空间",__func__);
//    return  [self allocWithZone:zone];
//}

- (instancetype)init {
    NSLog(@"%s,初始化空间",__func__);
    return  [self init];
}

//- (instancetype)initWithCoder:(NSCoder *)aDecoder {
//     NSLog(@"%s,从归档文件总加载",__func__);
//    return [super initWithCoder: aDecoder];
//}

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
     NSLog(@"%s,从Nib二进制文件中加载",__func__);
    return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
}


- (void)loadView {
    NSLog(@"%s,加载控制器的唯一视图View",__func__);
    [super loadView];
}

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
     NSLog(@"%s,视图的size发生改变",__func__);
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}

- (void)viewDidLoad {
    NSLog(@"%s,视图已经加载出来了",__func__);
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated {
        NSLog(@"%s,视图将要显示在屏幕界面上了",__func__);
    [super viewWillAppear:animated];
}

//- (void)viewWillLayoutSubviews {
//        NSLog(@"%s,视图开始布局自视图了",__func__);
//    [super viewWillLayoutSubviews];
//    UIButton* button = [[UIButton alloc]initWithFrame:CGRectMake(20, 20, 100, 30)];
//    [button setTitle:@"test btn" forState:UIControlStateNormal];
//    [button setTintColor:[UIColor greenColor]];
//    [self.view addSubview:button];
//}
//
//- (void)viewDidLayoutSubviews {
//        NSLog(@"%s,视图的子视图已经布局完了",__func__);
//    [super viewDidLayoutSubviews];
//}

- (void)viewDidAppear:(BOOL)animated {
        NSLog(@"%s,视图已经出现在屏幕上了",__func__);
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
        NSLog(@"%s,视图将要消失了",__func__);
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated {
        NSLog(@"%s,视图已经消失了",__func__);
    [super viewDidDisappear:animated];
}


#pragma mark 可选择性的
- (void)loadViewIfNeeded {
    [super loadViewIfNeeded];
}

 

posted @ 2016-03-10 23:38  阿甘左  阅读(2897)  评论(0编辑  收藏  举报