iOS Programming 6-1(View Controllers)
前面讲过了view和View hierachy,为了让view在window上显示,我们都是直接把一个view加到应用的window里面去,今天要讲的东西比view更高级一层,他叫view controller.他的职责是创建view,响应view的事件,管理view的层级关系,把view加到window里.
我会结合一个实际的应用来阐述view controller,这个应用最后出来的效果会想下面这样:
屏幕下面有一个tab,可以用来切换屏幕,左边按钮对应的屏幕和上一章讲到的view一样,右边的view是一个计时器.
Subclass UIViewController
我们首先创建一个空项目,并把上一章创建的view类引用到这个项目中来,接着创建第一个view controller (WUSTLHypnosisViewController), 让他继承自UIViewController.
1 2 |
|
View of View Controller
每一个继承自UIVIewController的类都有一个对应的view,它定义在父类中:
1
|
|
这个属性指向controller的view hierachy中的root view,所以当一个view controller的root view被加到应用的window中后,这个view controller中在view hierachy中的所有view都被加进去了.
Lazy Loading
View Controller中的view不是应用一启动就全部加载的,而是遇到用户请求才开始加载,这样做的好处是节约了内存,提高了性能.
对于一个View Controller来说,有两种方法可以加载其对应的view:
- 覆写父类UIViewController的loadView方法
- 如果view是在Interface Builder中创建的,可以通过加载Nib文件来读取view
我们首先使用第一种方法来创建WUSTLHypnosisViewController的view,在WUSTLHypnosisViewController.m
文件里先import 之前创建的view,然后覆写loadView方法:
1 2 3 4 |
|
Setting the Root View Controller
这一步完成后,我们已经建立了一个view controller并把它和一个view连接起来.如果要想显示这个view controller里面的view,我们只需要把这个view controller加到window里面去即可.我们来到AppDelegate的
1
|
|
方法中,在里面创建view controller的实例,然后把这个实例加到应用的window中去:
1 2 3 4 5 6 7 8 9 10 11 |
|
在之前的教学中,我们是直接把一个view加到window中,例如:
1
|
|
现在我们是把一个view controller加到window的root view controller中,其实在window的setRootViewController方法中,他还是会把view controller里面的view取出来,然后执行上面那段代码.
这样我们就完成了第一个屏幕,接下来应该开始第二个屏幕内容了.首先还是建立一个UIViewController的子类,不过这一次我们选择使用另一种方式创建view – 读取XIB文件.
Create a View in Interface Builder
首先建立一个XIB文件.
然后点击XIB文件,拖一个UIView到空白处,这样我们就可以在Interface Builder上面加入各种view了.接下来我们选择DatePicker和UIButton拖到view里面,效果如下:
接下来我们到对应的.m文件里创建一个DatePicker的property和addReminder方法:
1 2 3 |
|
这里datePicker的属性是weak,这样做的好处是在这个view被销毁的时候,其子类也被销毁了.
1 2 3 |
|
现在我们有了view,并且在类里面也有对应的属性和方法,接下来就是把他俩连接起来,不过与第一个讲义不同的是,这个XIB文件不是在创建controller的时候创建的,而是后来单独创建的,所以还需要把它和一个view controller连接起来才行.打开view左侧的File’s Owner,
然后来到右边的属性栏,在class里面填写对应的view controller即可:
创建view的最后一步就是把interface builder中的元素和类里面的属性和方法hook起来,方法如第一个讲义里面那样.
Loading a Nib File
我们还是来到AppDelegate那个didFinishLaunch方法里面去,并加上如下的代码:
1 2 |
|
第一句话的意思是找到应用的bundle,bundle是一个应用里面的一个文件夹,里面主要装着可执行文件和一些资源(XIB文件).第二句话是初始化view controller并读取相应的NIB文件.其实上面的代码和接下来的代码效果是一样的:
1
|
|
因为如果直接调用init方法,系统最终还是会调用initWithNibName,所以调用init只是相当于把initWithNibName方法的两个参数都设为nil,不过系统会默认到当前应用的bundle下面去找对应的资源,他会去尝试找与当前view controller同名的Nib文件(Nib是XIB编译后的产物),所以为了方便起见,我们一般把XIB文件的名字和view controller的名字保持一致.