天天看点

iOS开发系列--视图切换概述UITabBarControllerUINavigationController模态窗口

在ios开发中视图的切换是很频繁的,独立的视图应用在实际开发过程中并不常见,除非你的应用足够简单。在ios开发中常用的视图切换有三种,今天我们将一一介绍:

<a href="http://www.cnblogs.com/kenshincui/p/3940746.html#uitabbarcontroller">uitabbarcontroller</a>

<a href="http://www.cnblogs.com/kenshincui/p/3940746.html#uinavigationcontroller">uinavigationcontroller</a>

<a href="http://www.cnblogs.com/kenshincui/p/3940746.html#modalwindow">模态窗口</a>

ios三种视图切换的原理各不相同:

uitabbarcontroller:以平行的方式管理视图,各个视图之间往往关系并不大,每个加入到uitabbarcontroller的视图都会进行初始化即使当前不显示在界面上,相对比较占用内存。

uinavigationcontroller:以栈的方式管理视图,各个视图的切换就是压栈和出栈操作,出栈后的视图会立即销毁。

uimodalcontroller:以模态窗口的形式管理视图,当前视图关闭前其他视图上的内容无法操作。

uitabbarcontroller是apple专门为了利用页签切换视图而设计的,在这个视图控制器中有一个uitabbar控件,用户通过点击tabbar进行视图切换。我们知道在uiviewcontroller内部有一个视图,一旦创建了uiviewcontroller之后默认就会显示这个视图,但是uitabbarcontroller本身并不会显示任何视图,如果要显示视图则必须设置其viewcontrollers属性(它默认显示viewcontrollers[0])。这个属性是一个数组,它维护了所有uitabbarcontroller的子视图。为了尽可能减少视图之间的耦合,所有的uitabbarcontroller的子视图的相关标题、图标等信息均由子视图自己控制,uitabbarcontroller仅仅作为一个容器存在。

iOS开发系列--视图切换概述UITabBarControllerUINavigationController模态窗口

假设现在有一个kctabbarviewcontroller(继承于uitabbarcontroller),它内部有一个kcwebchatviewcontroller、一个kccontactviewcontroller。

1.首先创建一个kctabbarviewcontroller继承于uitabbarcontroller(代码是默认生成的,不再贴出来)。

2.其次创建两个子视图,在这两个子视图控制器中设置对应的名称、图标等信息。

kcwebchatviewcontroller.m

kccontactviewcontroller.m

3.在应用程序启动后设置tab bar视图控制器的子视图,同时将tab bar视图控制器作为window的根控制器。

appdelegate.m

运行效果:

iOS开发系列--视图切换概述UITabBarControllerUINavigationController模态窗口

对于uitabbarcontroller简单总结如下:

uitabbarcontroller会一次性初始化所有子控制器,但是默认只加载第一个控制器视图,其他视图控制器只初始化默认不会加载,为了能够将其他子控制器也正常显示在tab bar中我们访问了每个子视图控制器的视图以便调用其视图加载方法(viewdidload);当然,既然会调用子视图的初始化方法,当然也可以将视图控制器的tabbaritem属性设置放到init方法中设置,如此则不用再遍历其视图属性了。

每个视图控制器都有一个tabbarcontroller属性,通过它可以访问所在的uitabbarcontroller,而且对于uitabbarcontroller的直接子视图其tabbarcontroller等于parentviewcontroller。

每个视图控制器都有一个tabbaritem属性,通过它控制视图在uitabbarcontroller的tabbar中的显示信息。

tabbaritem的image属性必须是png格式(建议大小32*32)并且打开alpha通道否则无法正常显示。

注意:使用storyboard创建uitabbarcontroller的内容今天不再着重讲解,内容比较简单,大家可以自己试验。

uinavigationcontroller是一个导航控制器,它用来组织有层次关系的视图,在uinavigationcontroller中子控制器以栈的形式存储,只有在栈顶的控制器能够显示在界面中,一旦一个子控制器出栈则会被销毁。uinavigationcontroller默认也不会显示任何视图(这个控制器自身的uiview不会显示),它必须有一个根控制器rootviewcontroller,而且这个根控制器不会像其他子控制器一样被销毁。

iOS开发系列--视图切换概述UITabBarControllerUINavigationController模态窗口

下面简单通过几个视图模拟一下微信添加好友的功能,假设有一个导航控制器,它的根控制器为好友列表控制器kcfriendviewcontroller,通过它可以导航到添加qq联系人视图kcqqcontactviewcontroller,在qq联系人视图又可以导航到公共账号视图kcpublicaccountviewcontroller。

1.首先在应用代理启动后初始化一个导航控制器并设置其根控制器为kcfriendviewcontroller

2.在好友列表视图控制器中设置导航栏左右按钮,并且设置点击右侧按钮导航到添加qq联系人视图

3.在qq联系人视图右侧导航中添加一个导航到公共账号的按钮

4.在公共账号视图中在导航栏右侧设置一个按钮用于直接返回根视图

uinavigationcontroller默认显示一个根控制器,这个根视图必须指定(前面我们说过uinavigationcontroller和uitabbarcontroller类似仅仅作为导航容器,本身并不会显示视图),通过根控制器导航到其他下一级子视图。

在子视图中可以通过navigationcontroller访问导航控制器,同时可以通过navigationcontroller的childviewcontrollers获得当前栈中所有的子视图(注意每一个出栈的子视图都会被销毁)。

uinavigationcontroller导航是通过上方导航栏进行的(类似的uitabbarcontroller是通过下方uitabbar进行导航),每个放到uinavigationcontroller栈中的子视图都会显示一个导航栏,可以通过子控制器(包括根控制器)的navigationitem访问这个导航栏,修改其左右两边的按钮内容。

默认情况下除了根控制器之外的其他子控制器左侧都会在导航栏左侧显示返回按钮,点击可以返回上一级视图,同时按钮标题默认为上一级视图的标题,可以通过backbarbuttonitem修改。下一级子视图左侧返回按钮上的标题的显示优先级为: 导航栏返回按钮backbarbuttonitem的标题(注意不能直接给backbarbuttonitem的标题赋值,只能重新给backbarbuttonitem赋值)、导航栏navigationitem的标题,视图控制器标题。

演示效果:

iOS开发系列--视图切换概述UITabBarControllerUINavigationController模态窗口

鉴于很多初学者在学习uinavigationcontroller时看到的多数是使用storyboard方式创建导航,而且storyboard中的segue很多初学者不是很了解,这里简单对storyboard方式创建导航进行介绍。

下面简单做一个类似于ios系统设置的导航程序,系统默认进入settings视图控制器,在settings界面点击general进行general视图,点击sounds进入sounds视图,就那么简单。

1.首先在main.storyboard中拖拽一个uinavigationcontroller将应用启动箭头拖拽到新建的uinavigationcontroller中将其作为默认启动视图,在拖拽过程中会发现uinavigationcontroller默认会带一个uitableviewcontroller作为其根控制器。

2.设置uitableviewcontroller的标题为“settings”,同时设置uitableview为静态表格并且包含两行,分别在两个uitableviewcell中放置一个uilabel命名为”general”和“sounds”。

3.新建两个uitableviewcontroller,标题分别设置为“general”、“sounds”,按住ctrl拖拽“settings”的第一个uitableviewcell到视图控制器“general”,同时选择segue为“push”,拖拽第二个uitableviewcell到视图控制器“sounds”,同时选择segue为“push”。

到这里其实我们已经可以通过settings视图导航到general和sounds视图了,但是storyboard是如何处理导航的呢?

前面我们看到导航的过程是通过一个名为“segue”连接创建的(前面采用的是push方式),那么这个segue是如何工作的呢?segue的工作方式分为以下几个步骤:

1.创建目标视图控制器(也就是前面的general、sounds视图控制器)

2.创建segue对象

3.调用源视图对象的prepareforsegue:sender:方法

4.调用segue对象的perform方法将目标视图控制器推送到屏幕

5.释放segue对象

要解释上面的过程首先我们定义一个kcsettingstableviewcontroller控制器,它继承于uitableviewcontroller,然后在storyboard中设置“settings”视图控制器的class属性为kcsettingstableviewcontroller。同时设置导航到“general”视图控制器的segue的identifier为“generalsegue”,设置导航到“sounds”控制器的segue的identifier为“soundssegue”。

然后修改kcsettingstableviewcontroller.m添加如下代码:

此时运行程序导航我们会发现此方法会被调用的同时可以打印源视图控制器和目标视图控制器的信息,这一步对应上面所说的第三个步骤。

接着在”settings”视图控制器的导航栏左右两侧分别放一个uibarbuttonitem并添加对应事件代码如下:

此时运行程序发现,使用两个按钮同样可以导航到对应的视图控制器,这一步对应上面第四个步骤,只是默认情况下是自己执行的,这里我们通过手动调用来演示了这个过程。

运行效果如下:

iOS开发系列--视图切换概述UITabBarControllerUINavigationController模态窗口

模态窗口只是视图控制器显示的一种方式(在ios中并没有专门的模态窗口类),模态窗口不依赖于控制器容器(例如前两种视图切换一个依赖于uitabbarcontroller,另一个依赖于uinavigationcontroller),通常用于显示独立的内容,在模态窗口显示的时其他视图的内容无法进行操作。

模态窗口使用起来比较容易,一般的视图控制器只要调用- (void)presentviewcontroller:(uiviewcontroller *)viewcontrollertopresent animated: (bool)flag completion:(void (^)(void))completion ns_available_ios(5_0);方法那么参数中的视图控制器就会以模态窗口的形式展现,同时调用- (void)dismissviewcontrolleranimated: (bool)flag completion: (void (^)(void))completion ns_available_ios(5_0);方法就会关闭模态窗口。

下面的示例中演示了一个登录操作,点击主界面左上方登录按钮以模态窗口的形式展现登录界面,用户点击登录界面中的登录按钮就会返回到主界面。特别强调一点在下面的示例中导航栏是手动创建的,而不是采用uinavigationcontroller,为了帮助大家熟悉导航栏使用同时也了解了uinavigationcontroller中导航栏的本质。

1.首先创建一个登录界面,在界面中只有两个输入框和一个登录按钮

2.定义主界面视图控制器kcmainviewcontroller,在左上角放一个登录按钮用于弹出登录界面

假设用户名输入“kenshincui”,密码输入“123”就认为登录成功,否则登录失败。同时登录成功之后在主视图控制器中显示用户名并且登录按钮变成“注销”。要实现这个功能主要的问题就是如何把登录后的用户名信息传递到主界面?由此引出一个问题:多视图参数传递。

在ios开发中常用的参数传递有以下几种方法:

采用代理模式

采用ios消息机制

通过nsdefault存储(或者文件、数据库存储等)

通过appdelegate定义全局变量(或者使用uiapplication、定义一个单例类等)

通过控制器属性传递

今天我们主要采用第一种方式进行数据传递,这在ios开发中也是最常见的一种多视图传参方式。使用代理方式传递参数的步骤如下:

1.定义协议,协议中定义好传参时所需要的方法

2.目标视图控制器定义一个代理对象

3.源视图控制器实现协议并在初始化目标控制器时指定目标控制器的代理为其自身

4.需要传参的时候在目标窗口调用代理的协议方法

具体代码如下:

kcmainviewcontroller.h

kcmainviewcontroller.m

kcloginviewcontroller.h

kcloginviewcontroller.m

在上面的代码中,点击登录可以跳转到登录界面,如果用户名、密码输入正确可以回传参数到主界面中(不正确则给出提示),同时修改主界面按钮显示内容。如果已经登录则点击注销会弹出提示,点击确定注销则会注销登录信息。在代码中我们还用到了uiactionsheet和uialert,这两个控件其实也是模态窗口,只是没有铺满全屏,大家以后的开发中会经常用到。

假设登录之后在主视图控制器右上角点击“我”可以弹出当前用户信息如何实现呢?这个时候我们需要从主视图控制器传递参数到子视图控制器,和前面的传参刚好相反,这个时候我们通常使用上面提到的第五个方法,设置目标视图控制器的属性。

1.首先修改一下主视图控制器

2.添加展示用户信息的控制器视图

kcmeviewcontroller.h

kcmeviewcontroller.m

前面代码中除了演示了模态窗口的使用还演示了两种多视图参数传递方法,其他方法日后我们再做介绍。最后完整展现一下整个示例程序:

iOS开发系列--视图切换概述UITabBarControllerUINavigationController模态窗口

<a href="http://pan.baidu.com/s/1sjexh5v" target="_blank"></a>