UIViewController

  1. 父类是UIResponder(父类是NSObject)
  2. 概念:凡是继承自UIViewController的对象,都叫做控制器
  3. 作用:负责处理软件界面的各种事件、负责软件界面的创建和销毁
  4. 注意:每个UIViewController专门管理一个软件界面(view),它管理的其他所有控件都是这个view的子控件或“孙控件”
    // UIViewController用view这个强指针指着它负责的软件界面,所以只要控制器不销毁,软件界面就不会销毁
    NSLog(@"%@",viewController.view);
    

控制器的创建

通过storyboard创建控制器

  1. 详见storyboard中“系统加载指定storyboard的流程”

通过xib创建控制器

  1. 步骤:
    1. 首先创建一个Xib文件
    2. Xib文件需要拖一个View描述控制器的View
    3. 需要把Xib上的View与控制器连线,并设置Xib的File'owner为控制器
    // 通过xib创建窗口的根控制器:initWithNibName
    // NibName:xib名称
    ViewController *vc = [[ViewController alloc] initWithNibName:@"VC" bundle:nil];
    self.window.rootViewController = vc;
    
  • xib注意点:
    1> xib里面必须有一个view描述控制器的view,因为控制器的view 属性必须有值。
    2> xib需要指定描述哪一个控制器,描述UIView不需要,因为xib里面可以描述很多UIView,不能固定死,但是控制器就不一样了,一个xib就用来描述一个控制器。(设置file owner为控制器,即设置custom class)
    3> xib里面可能有很多view,需要拖线指明哪个是控制器的view
  1. 假设通过Xib创建XXXViewController控制器对象顺序
    1. 如果nibName不为空,会去创建对应的xib
    2. 如果nibName为nil,首先会去查找XXXViewController.xib,如果有,就会去加载XXXViewController.xib
    3. 如果没有找到,就会去找XXXView.xib,如果有,也会去加载
    4. 都没有找到,就会生成一个空的view
    5. init底层就会调用initWithNibName:bundle:(注意不会通过storyboard的方式加载)
    6. Xcode7之前是先找XXXView后找XXXViewController
  • xib如何快速创建控制器的view:
    1> 定义新的控制器的时候,勾选xib,会自动搞一个xib描述控制器的view.
    2> 会自动生成一个和控制器同名的xib,并且里面设置好了。

  • xib最后会转成Nib文件,关于nib的介绍详见UINib

  • xib和storyboard的区别 storyboard已经指定了控制器的view,不需要我们管,xib需要我们手动设置view的custom class和owner。

控制器的view

  1. 控制器View的决定权:[viewController setView:view]——>viwDidLoad——>重写LoadView>storyboard>xib


    控制器view加载.png
  • 控制器的view是懒加载的
    -(UIView *)view
    {
        if (_view == nil) {
            [self loadView];
            [self viewDidLoad];
        }
    
        return _view;
    }
    
  • loadView的时机与重写loadView的意义
    1. 第一次加载控制器的view时才会调用loadView
    2. 使用场景:若想自定义控制器的View就可重写这个方法,例如:控制器的View想展示一张图片,或者创建UIWebView等;
    3. 注意:一旦重写了loadView,就不要调用[super loadView],否则会重复创建
     - (void)loadView
    {
    // 如果当前控制器是窗口的根控制器,它的view可以不设置尺寸。
    UIImageView *vcView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"1"]];
    self.view = vcView;
    }
    
  1. 可以用isViewLoaded方法判断一个UIViewController的view是否已经被加载

  2. 只要创建了控制器,无论是通过storyboard,还是xib,还是手动,都会自动创建view,如果没有指定view,创建的是一个空的view

  • 控制器view的透明度
    //alloc init创建空View,默认几乎透明(几乎透明:alpha > 0.01)
    ViewController *vc = [[ViewController alloc] init];
    vc.view.backgroundColor = [UIColor clearColor];//空view默认的颜色
    //vc.view.backgroundColor = [UIColor whiteColor];
    
    // 如果一个View完全透明,可以直接点击后面的东西,可以完全穿透。(完全透明:alpha <= 0.01);另外要注意颜色与透明度无关
    vc.view.alpha = 0.02;
    

控制器的生命周期方法

  1. 生命周期方法:即控制器的view什么时候创建,什么时候销毁,只要以view开头一般都是控制器view的生命周期


    生命周期方法.png
  1. 具体的生命周期方法:(布局控件方法调用频繁,view显示与消失前都会调用)
// 控制器的view加载完成时调用
- (void)viewDidLoad {
    [super viewDidLoad];

    //以后打印控制器的View真实尺寸,一般不再viewDidLoad去打印,因为不准确(还在加载数据),在viewDidAppear中打印
}

// 控制器的view即将显示时调用
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

// 控制器的view完全显示时调用
// 一般用来调试控制器view的真实尺寸
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

//  控制器的view即将消失时调用
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
}

// 控制器的view完全消失的时候调用
- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

// 控制器的view即将布局子控件的时候调用
- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
}

// 控制器的view布局子控件的完成时候调用
- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
}

// ARC中必须要了解
// viewDidLoad -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews ->  viewDidAppear -> viewWillDisappear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidDisappear    //可以看出布局控件方法调用频繁


// 非ARC
// Unload:卸载,当前view销毁
//- (void)viewWillUnload
//{
//}

// 当前view卸载完成,完全销毁的时候调用
- (void)viewDidUnload
{
    self.datas = nil;
}

//  MRC中内存机制解释
//- (void)setDatas:(NSArray *)datas
//{
//    if (datas != _datas) {
//        [_datas release];
//        _datas = [datas retain];
//    }
//}

当出现内存警告时,控制器的处理流程

  1. didReceiveMemoryWarning,当控制器接收内存警告的时候调用
    • 内存警告传递过程:手机内存不足产生事件->通知应用程序->调用应用程序代理方法->把事件传递给窗口->窗口传给控制器->调用控制器内存警告的方法。


      内存警告处理.png
  • 当控制器接收内容警告,会销毁没有显示的控制器的view。

  • 调用viewWillUnload,viewDidUnload,销毁控制器的view

  • viewDidUnload里面一般清空显示在view里面的数据
    1. 为什么要清空显示view的数据:展示数据的view都不存在了,这些数据也就没有用处了,因为数据主要是用来展示在view上
    2. 清空数据建议使用nil,清空数据,在非arc和arc都通用。arc是不能使用release,而且非arc下,self.datas = nil;做的事情更多。

  • didReceiveMemoryWarning会导致viewDidLoad重新调用。

    • 当收到内存警告,导航控制器的子控制器的view有可能被干掉,他如果没有显示的话,当下次使用这个控制器的时候就会调用,加载view。

UIViewController管理状态栏

    从iOS7开始,系统提供了2种管理状态栏的方式
  1. 在iOS7中,默认情况下,状态栏都是由UIViewController管理的(每一个UIViewController都可以拥有自己不同的状态栏),UIViewController实现下列方法就可以轻松管理状态栏的可见性和样式

    // 设置状态栏是否隐藏
    viewController.prefersStatusBarHidden = YES;
    
    // 修状态栏样式
    - (UIStatusBarStyle)preferredStatusBarStyle
    {
        return UIStatusBarStyleLightContent;
    }
    @end
    
  2. 通过UIApplication管理(一个应用程序的状态栏都由它统一管理)
    1. 需在info.plist中配置


    Snip20151108_152.png
         2. 在Info.plist中做了图中的配置,可能会出现以下警告信息
    
Snip20151108_153.png
```objc
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

// 状态栏的可见性
// 隐藏状态栏
app.statusBarHidden = YES;
// 动画隐藏状态栏
[app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]
```

父子控制器

  1. 开发原则:如果子控件添加到父控件中时,如果子控件是控制器的view,需要将子控件的控制器添加到父控件的控制器。
  • 屏幕控件切换显示时,某个控件不显示,一般是将控件从父控件移除,但不会立即移除对应的子控制器。
    一来方便下次使用时快速处理时间与显示视图;
    二来是子控制器销毁时,其视图也会被销毁,而不会造成内存泄露。
  • 开发中遇到内存警告时,没有显示的控件,要销毁其控制器以释放内存。
  • 任何控制器都可以添加子控制器,都可以管理子控制器
  • 父控制器的UINavigationController(导航控制器)UITabBarController(标签控制器),它的子控制器都能拿到,它的底层是:
    1. 判断下自己是不是导航控制器和标签控制器的子控制器,ChildViewController不是导航控制器和标签控制器子控制器则继续判断
    2. 判断下父控制器是不是导航控制器和标签控制器的子控制器,是就可以拿到
    3. 继续一直判断,直到没有父控制器
  • Modal也是同样的原理:
    1. 判断下自己是否被Modal,如果被modal,就把自己dismiss
    2. 如果不是,判断下自己父控制器是否被modal,如果被modal,就把自己dismiss
    3. 一直判断,直到没有父控制器
// 子控制器(只读)
@property(nonatomic,readonly) NSArray<__kindof UIViewController *> *childViewControllers NS_AVAILABLE_IOS(5_0);


// 添加子控制器
- (void)addChildViewController:(UIViewController *)childController NS_AVAILABLE_IOS(5_0);

// 移除出父控制器
- (void) removeFromParentViewController

UIViewController常用属性

// 标题
@property(nullable, nonatomic,copy) NSString *title;

// 父控制器
@property(nullable,nonatomic,weak,readonly) UIViewController *parentViewController;

// modal它的控制器
@property(nullable, nonatomic,readonly) UIViewController *presentedViewController  NS_AVAILABLE_IOS(5_0);

// 它modal的控制器
@property(nullable, nonatomic,readonly) UIViewController *presentingViewController NS_AVAILABLE_IOS(5_0);

判断当前ViewController是push还是present的方式显示的

NSArray *viewcontrollers=self.navigationController.viewControllers;

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

推荐阅读更多精彩内容