iOS开发视图控制器(ViewController)调用[super viewXXX]的简单理解

来源:互联网 发布:java设置默认编码 编辑:程序博客网 时间:2024/06/05 03:44

iOS开发视图控制器(ViewController)调用[super viewXXX]的简单理解

本人刚刚进入iOS开发行业,许多理解可能存在错误,希望各位老司机看到能够指出。那么言归正传,记得在学习iOS开发的时候,老师讲过,- (void)viewDidLoad 、这类的函数中,要先调用父类的方法即:[super viewDidLoad]来完成一些事情,那么这些方法究竟做了什么呢?于是我就创建了多个类,他们依次继承。如下图:创建的依次继承的类
如英文所示ViewController继承SonViewController、SonViewController继承自SelfViewController、SelfViewController继承自Father…
当然我创建的跟视图控制器是ViewController的实例。
开始我想,既然调用方法,那么可以断点进来,看是否每一句都执行,于是我在各自的viewDidLoad中输入的如下代码。

NSLog(@"I am grandpa"); //grandpa视图控制器中NSLog(@"I am father"); //father视图控制器中NSLog(@"I am myself"); //self视图控制器中NSLog(@"I am son"); //son视图控制器中

viewWillAppear中添加了如下代码

NSLog(@"Grandpa's viewWillAppear!");//grandpa视图控制器中NSLog(@"Father's viewWillAppear!");//father视图控制器中NSLog(@"My viewWillAppear!");//self视图控制器中NSLog(@"Son's viewWillAppear!");//son视图控制器中

运行程序控制台输出为:
控制台输出

显然我们增加的这些代码都是依次执行了的,viewController实例创建后经访问,开始执行viewDidLoad,然后依次调用[super viewDidLoad],从grandpa的viewDidLoad依次执行到viewController的viewDidLoad。然后viewController的实例,开始执行viewWillAppear,接着又是一串[super viewWillAppear] 调用。
不知道大家又没有注意到这其中的一个问题:

  • 在创建viewController实例后,会自动控制viewDidLoad、viewWillAppear等与视图控制器周期相关的函数的调用,而通过[super viewDidLoad]这种方法调用的就只是会执行被调用的方法;也就是说:视图控制器会自动在适当的时机控制着与视图控制器生命周期相关的函数的调用。

我又陷入了沉思,那么通过super这种调用是将所有的代码都执行呢?还是执行部分代码,对于界面的布局又是怎么样的呢?对于[self.view addSubview: xxx]这样的代码又是怎样的呢?(毕竟对于新人来说很容易被self、super这样字眼本身的意义所误导)

于是我在GrandpaViewController的viewDidLoad中修改了背景色:

self.view.backgroundColor = [UIColor yellowColor];

运行后,显示的颜色为黄色。凭直觉,我认为如果我在fatherViewController的viewDidLoad中也修改背景色,那么这个背景色将是fatherViewController修改后的颜色,进行尝试后得到了验证。

接着我在GrandpaViewController的viewDidLoad中增加了一个button并且绑定了事件:

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];button.frame = CGRectMake(0, 0, 100, 200);[button setTitle:@"爷爷按钮" forState:UIControlStateNormal];[self.view addSubview:button];[button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];

buttonAction

- (void)buttonAction {NSLog(@"GrandpaButtonAction");}

运行模拟机如下图:
爷爷按钮
点击按钮控制台输出
这里写图片描述

接着我又在fatherViewController的viewDidLoad中也增加了一个按钮并绑定事件:

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];button.frame = CGRectMake(200, 0, 100, 200);[button setTitle:@"什么鬼" forState:UIControlStateNormal];[button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:button];

buttonAction

- (void)buttonAction {NSLog(@"fatherButtonAction");}

运行模拟机截图为:
这里写图片描述

大家可以猜一猜运行结果,当我点击”爷爷按钮”的时候,控制台会输出GrandpaButtonAction;当我点击”什么鬼”按钮时会输出fatherButtonAction。 然而并不是这个样子的,不管我点击哪一个按钮都输出的是fatherButtonAction。 这是为什么呢?原因在于两个按钮绑定的方法是相同名字的。在father中又写一次相当于重写了该方法(私有方法)。
看来通过这种调用,会执行与布局相关的代码(其实会执行所有代码)。

那么问题来了,怎么理解每一个viewDidLoad中的self.xxx呢?当我们用
ViewController *viewController = [[ViewController alloc] init];这种方法创建视图控制器时,他会用最原始声明alloc init这种方法来创建一个实例。然后逐步通过[super xxx]的方式来初始化,也就是说只有一个实例,那么通过[super xxx]方法来执行的self 都是指向的同一个地方,都是那一个实例。为了验证,我在GrandViewController的viewDidLoad中增加了

 id x = self;NSLog(@"%@",x);

在ViewController的viewDidLoad中增加了

NSLog(@"%@",self);

控制台输出如下:
这里写图片描述
输出的结果验证了以上说法。

  • 因此在视图控制器的周期相关函数中,最好先初始化父类,即是先调用[super xxx]。

希望本文能够让广大的入门同胞,对视图控制器的[super xxx]以及继承有一定的理解,如有发现文中错误的地方,欢迎指出!

2 0
原创粉丝点击