博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IOS开发实战-UIViewController及生命周期
阅读量:2222 次
发布时间:2019-05-08

本文共 4755 字,大约阅读时间需要 15 分钟。

UIViewController及生命周期

UIViewController是UIKit框架中Controller部分的基础所有界面都是基于UIViewController搭建出来的

UIViewController的生命周期

生命周期指对象从创建到被销毁的整个过程,保持内存的平衡和而程序高效运行当需要一个对象时,他会被创建并分配内存空间当它不再被需要时,应该被系统释放回收UIViewController对象从创建到释放过程中会依次调用许多生命周期函数

打开Xcode,创建一个名为UIViewControllerTest的工程

创建工程操作见上一篇:

创建完成后,模板代码会自动生成一个ViewController类

代码结构

ViewController类继承自UIViewController,

并与Main,storyboard中初始视图控制器关联,
简单来说,这个类创建了一个视图控制器,作为工程的根视图控制器
继承关系

UIViewController中生命周期相关函数:

// 类的初始化方法+ (void)initialize;// 对象初始化方法- (instancetype)init;// 从归档初始化- (instancetype)initWithCoder:(NSCoder *)coder;// Xib初始化后-(void)awakeFromNib;// 加载视图-(void)loadView;// 将要加载视图- (void)viewDidLoad;// 将要布局子视图-(void)viewWillLayoutSubviews;// 已经布局子视图-(void)viewDidLayoutSubviews;// 内存警告- (void)didReceiveMemoryWarning;// 将要展示-(void)viewWillAppear:(BOOL)animated;// 已经展示-(void)viewDidAppear:(BOOL)animated;// 将要消失-(void)viewWillDisappear:(BOOL)animated;// 已经消失-(void)viewDidDisappear:(BOOL)animated;// 被释放-(void)dealloc;

在ViewController.m中覆写UIViewController方法

测试并跟踪声明周期函数的执行顺序:

////  ViewController.m//  UIViewController////  Created by Brave on 18/4/29.//  Copyright © 2018年 com.Brave. All rights reserved.// #import "ViewController.h"int tip = 0;// 对程序运行过程进行标记@interface ViewController ()@end// ViewController是UIViewController的子类@implementation ViewController// 类的初始化方法+(void)initialize{    // 在子类中覆盖父类方法时,需先调用父类此方法    [super initialize];    NSLog(@"%d initialize", ++tip);}// 对象初始化方法// 只允许调用一次,并且要与 alloc方法 写在一起,// 在init方法中申请的内存,要在dealloc方法中释放(或者其他地方);- (instancetype)init{    self=[super init];    if(self){    }    NSLog(@"%d init", ++tip);    return self;}// 从归档初始化- (instancetype)initWithCoder:(NSCoder *)coder{    self = [super initWithCoder:coder];    if(self){    }    NSLog(@"%d initWithCoder", ++tip);    return self;}// 使用Xib初始化后会调用此方法,一般不会重写此方法;-(void)awakeFromNib{    [super awakeFromNib];    NSLog(@"%d awakeFromNib", ++tip);}// 加载视图// 如果使用Xib创建ViewController,就不要重写该方法。一般不会修改此方法-(void)loadView{    [super loadView];    NSLog(@"%d loadView", ++tip);}// 将要加载视图// 视图加载完成之后被调用,这个方法很重要,可以在此增加一些自己定义的控件,// 注意,此时view的frame不一定是显示时候的frame,真实的frame会在 - (void)viewDidAppear: 后。// 在iOS6.0+版本中在对象的整个生命周期中只会被调用一次// 这里要注意在iOS3.0~iOS5.X版本中可能会被重复调用,// 当ViewController收到内存警告后,会释放View,并调用viewDidUnload,// 之后会重新调用viewDidLoad,所以要支持iOS6.0以前版本的童鞋要注意这里的内存管理。- (void)viewDidLoad {    [super viewDidLoad];    NSLog(@"%d viewDidLoad", ++tip);    // Do any additional setup after loading the view, typically from a nib.}// 将要布局子视图-(void)viewWillLayoutSubviews{    [super viewWillLayoutSubviews];    NSLog(@"%d viewWillLayoutSubviews", ++tip);}// 已经布局子视图-(void)viewDidLayoutSubviews{    [super viewDidLayoutSubviews];    NSLog(@"%d viewDidLayoutSubviews", ++tip);}// 内存警告- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    NSLog(@"%d didReceiveMemoryWarning", ++tip);    // Dispose of any resources that can be recreated.}// 将要展示// 可在此处加载图片,和其他占内存的资源-(void)viewWillAppear:(BOOL)animated{    [super viewWillAppear:animated];    NSLog(@"%d viewWillAppear", ++tip);}// 已经展示-(void)viewDidAppear:(BOOL)animated{    [super viewDidAppear:animated];    NSLog(@"%d viewDidAppear", ++tip);}// 将要消失// 可在此将占用内存比较大的资源先释放掉,在viewWillAppear: 中重新加载,如:图片/声音/视频。// 如果View已经隐藏而又在内存中保留这些在显示前不会被调用的资源,// 那么App闪退的几率会增加,尤其是ViewController比较多的时候;-(void)viewWillDisappear:(BOOL)animated{    [super viewWillDisappear:animated];    NSLog(@"%d viewWillDisappear", ++tip);}// 已经消失-(void)viewDidDisappear:(BOOL)animated{    [super viewDidDisappear:animated];    NSLog(@"%d viewDidDisappear", ++tip);}// 被释放// dealloc方法时唯一一个不需要并且也不能在实现时调用父类方法的函数,// 这个函数在ARC(自动引用计数)环境中不再被开发者需要,// 但开发者依然可以重写这个函数来检测内存的释放情况// 不要手动调用此方法,当引用计数值为0的时候,系统会自动调用此方法。-(void)dealloc{    NSLog(@"%d dealloc", ++tip);}@end

以上代码在ViewController.m中创建了一个全局变量tip

使用tip对程序运行过程进行标记,通过log日志查看函数执行顺序
执行程序,观察Log输出:
这里写图片描述

从Log中可以清晰看到UIViewController创建时的生命周期函数调用顺序

(不包括销毁过程及从不同来源初始化UIViewController的过程)

initialize:    并不会在每次创建对象时被调用,    只在这个类第一次创建对象时被调用做一些类的准备工作    如果有继承的子类未实现initialize方法,    第一次创建子类对象时,父类会代替子类调用initialize方法init和initWithCoder都是用作初始化对象    init:从代码进行初始化    initWithCoder:从归档文件进行初始化awakeFromNib:    从xib或storyboard中加载UIViewController将要被激活时调用loadView:    加载UI视图初始化方法,UIViewController生命周期中只调用一次viewDidLoad:    视图加载完成后调用,此时视图控制器基本工程已初始化完成    一般将一些Controller额外定义功能的初始化工作放在此函数中viewWillAppear:    视图即将显示时调用viewWillLayoutSubviews:    视图将要布局其子视图时被调用viewDidLaySubviews:    视图布局完成其子视图时被调用viewDidAppear    视图显示后被调用

UIViewController被释放和销毁的过程调用:

viewWillDisappear:    在试图将要消失时调用,做一些数据保存和清理工作viewDidDisappear    视图已经消失时调用dealloc或deinit    对象的销毁方法,在对象释放时调用,    可通过在其中打印信息检查是否存在内存泄露等问题

UIViewController的视图层级结构:

UIViewController自带一个UIView类型的view视图这个view平铺在屏幕上,是视图控制器的根视图在视图控制器中添加UI控件都是添加在这个view上UIView通过addSubview方法添加子view视图子view视图也可以继续使用addsubview添加自己的子视图......

备注:

Xcode模拟器的Home键:Command-Shift-H

你可能感兴趣的文章
seq2seq 入门
查看>>
什么是 Dropout
查看>>
用 LSTM 做时间序列预测的一个小例子
查看>>
用 LSTM 来做一个分类小问题
查看>>
详解 LSTM
查看>>
按时间轴简述九大卷积神经网络
查看>>
详解循环神经网络(Recurrent Neural Network)
查看>>
为什么要用交叉验证
查看>>
用学习曲线 learning curve 来判别过拟合问题
查看>>
用验证曲线 validation curve 选择超参数
查看>>
用 Grid Search 对 SVM 进行调参
查看>>
用 Pipeline 将训练集参数重复应用到测试集
查看>>
PCA 的数学原理和可视化效果
查看>>
机器学习中常用评估指标汇总
查看>>
什么是 ROC AUC
查看>>
Bagging 简述
查看>>
详解 Stacking 的 python 实现
查看>>
简述极大似然估计
查看>>
用线性判别分析 LDA 降维
查看>>
用 Doc2Vec 得到文档/段落/句子的向量表达
查看>>