[ios开发教程]iOS开发 UIViewController与UINavigationController学习及使用

更新时间:2019-12-08    来源:ios    手机版     字体:

【www.bbyears.com--ios】

一、UIViewController的介绍

1)概念:UIViewController 即视图控制器,用来管理和控制页面跳转的一个类 ,iOS里面采用了MVC的体系结构,在UI方便的

具体表现为View加ViewController。所以UIViewController是iOS应用当中非常常用而且很重要的一个类;一般使用都是自己写

一个类继承UIViewController这个类。在UIViewController里面有一个很重要的属性那就是View,也就 是这个Controller对应的

View,MVC里面的V和C。可以通过覆盖其中的loadView方法来手动创建View然后把它设置到 Controller的属性中。

2)新建一个类FirstViewController 基础ViewController 将这个类交给window的主视图控制器管理 例如:  

1 FirstViewController *firstVC = [[FirstViewController alloc] init];
2 self.window.rootViewController = firstVC;

 
3)页面跳转方法 实例代码

方法一  :

//初始化第二个页面
_secondVC = [[SecondViewController alloc] init];
//从第一个页面跳转到第二个页面    
[self presentViewController:_secondVC animated:YES completion:^{
        
}];
//注意:此处的跳转页面对象一般定义成全局的 否则会出错

//对应的跳转返回方法:
//回到上一页面  注意:此方法写在第二个页面的.m文件中
[self dismissViewControllerAnimated:YES completion:^{
       
}];
 

方法二 :

[self.view addSubview:_secondVC.view];

//对应的跳转返回方法:
//回到上一页面  注意:此方法写在第二个页面的.m文件中
[self.view removeFromSuperview];
 

4)UIViewContrller初始化的时候backgroundColor默认是nil,并不是clearColor,所以我们在初始化视图控制器时要给视图控制器设置

一个不为clearColor的颜色  例如:

self.view.backgroundColor = [UIColor whiteColor];

 
二、UINavigationController 的介绍

1)概念:UINavigationController 即导航控制器是一个用于控制视图页面切换的一个类

2)UINavigationController  初始化实例代码

//初始化一个视图控制器
FirstViewController *firstVC = [[FirstViewController alloc] init];

//初始化一个导航控制器
//导航控制器中自身有个栈容器,初始化的时候一定要设置一个rootViewController座位导航控制器的基栈
//导航控制器的初始化一定需要一个根视图控制器
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:firstVC];
//设置window的rootVC为我们初始化的导航控制器实例
self.window.rootViewController = nav;
 

3)pushViewController 实现页面切换 例如:

//初始化SecondViewController
SecondViewController *secondVC = [[SecondViewController alloc] init];

//从页面1 跳转到页面2
[self.navigationController pushViewController:secondVC animated:YES];

 
4)popViewControllerAnimated 实现页面返回 例如:

//返回到上一个VC
[self.navigationController popViewControllerAnimated:YES];
// 注意:通过导航控制器push到另一个vc,一定是通过导航控制器pop回上一个页面。
//两种跳转方式一定是对应的返回方式

5)popToRootViewControllerAnimated 通过导航控制器,从导航控制器栈容器的第N的VC直接跳转到导航控制器的根视图控制器

例如:

[self.navigationController popToRootViewControllerAnimated:YES];

6)viewControllers 获取导航控制器的栈容器中的视图控制器数组 例如:

NSArray *vcArr = self.navigationController.viewControllers;
//获取第二个视图控制器
UIViewController *secondVC = [vcArr objectAtIndex:1];

[self.navigationController popToViewController:secondVC animated:YES];





UIViewController使用技巧!
 
UIViewController顾名思义,视图控制器应该在MVC设计模式中扮演控制层的角色。最开始的时候一直不理解为何有了UIView还要UIViewController做什么用,不都是向视图中增加view。如果你开发的应用界面非常的简单,确实没有这个必要,但是对于视图中复杂的数据显示和数据处理,如果没有这个控制器,这样会使得代码的继承深度大大增加,不利于代码的阅读,首先看下官方API对UIViewController的解释:The UIViewController class provides the fundamental view-management model for iPhone applications(视图控制器为Iphone的应用程序提供了基础的视图管理模型) You use each instance of UIViewController to manage a view hierarchy(你可以使用视图控制器管理视图的继承树)。从这里就可以看出,如果使用了视图控制器,你就可以方便的管理视图中的子视图,假如没有了这个控制器,可想而知每个视图岂不是都要用继承才能管理彼此的关系。

UIViewController的基础功能是管理界面中的view,但是一个复杂的应用程序肯定有好多的视图控制器,那么自然如果视图控制要有管理自己的功能就更加强大。先看API文档:View controllers rarely operate in isolation.

If your application uses a navigation or tab bar controller,or if your application presents views modally, then it typically has several view controllers interacting with each other to implement those navigation features(视图控制器很少单独使用。假如你的应用程序要使用导航或者转换条控制器,或许是你的应用程序要呈现模态的视图,明显的这里有很多的视图控制器相互关联来实现导航的功能)。所以可以看出,UINavigationController和UITabBarController是用来控制视图控制器的使用的,同样他们的跟视图也是UIViewController,这里就说明了UIViewController是自己可以控制自己的。这也是为何我们使用UINavigationController的时候不允许在把一个NavigationController推入堆栈中,这样极容易形成自己队递归调用自己,造成堆栈溢出。以下是使用UIViewController应该注意的地方。

1.首先看loadView和viewDidLoad的区别,两者都是用来初始化试图控制器中的视图如何显示的。还是先看官方API解释:If you create your views manually, you must override this method and use it to create your views.

If you use  Interface Builder to create your views and initialize the view controller  that is, you initialize the view using the initWithNibName:bundle: method, set the nibName and nibBundle properties directly, or create both your views and view controller in Interface Builder―then you must not override this method.(如果你手动创建一个视图控制器,你必须重载这个方法,去使用他创建你的视图。如果你使用Interface builder创建和初始化的视图控制器,你就不必重载此方法)。所以当你手动创建一个视图控制器的时候一定要注意重载loadView,否则你的视图将不回显示你增加的任何字视图。

2.viewDidUnLoad这个方法最容易误导人,先看API解释:Called when the controller’s view is released from memory(当控制器的视图从内存中释放的时候被调用),个人觉得官方的解释对英语非母语的国家的人来说,很容易理解为视图控制器release的时候,调用此方法。但是如果实际调试以下,视图控制器释放的时候不会调用该方法。再进一步分析API文档:This method is called as a counterpart to the viewDidLoad method.

It is called during  low memory conditions when the view controller needs to release its view

and any objects associated with that view to free up memory(这个方法是被调用相对于viewDidLoad方法的,在内存警告的情况下,当试图控制器需要释放它的视图和这个视图中相关联的任何对象来释放内存的时候,调用此方法)。这里还有一点要注意的时,当出现内存警告的时候,是调用正在显示的视图控制器的父视图控制器的viewdidUnload方法,而不是正在显示的视图控制器的viewDidUnload方法。因为如果调用了正在显示的视图控制器的viewDidUnload方法,那么用户正在看的界面就会消失,虽然释放了内存但是用户显然没法接受,自然要释放该视图下面看不到的视图控制器中的视图。被释放的视图,下次加载的时候再调用viewDidLoad的方法,所以ViewDidUnload的方法是和viewDidload方法相互对应的。

3.为了方便内存的管理,曾经写过这样的代码:

MyNibController  *nibController = [[myNibController alloc] initWithNibName:@"myNibController" bundle:nil];  
 
[self.view addSubview:nibController.view];  
 
[nibController release];  

分析下这样的代码潜在的危害,这个应该清楚一点当AddSubView这个方法调用的时候,nibController.view这个视图的引用计数就会加1。但是这里释放了nibController这个控制器,那么管理这个视图的控制器没有了,但是该视图确实还存在。想象下,就像你开动了汽车发动机,但是没有人驾驶,任之随便的跑,这辆汽车会带来多大的危害。这里很容易出问题的地方就是,如果再nibController中写了一个按钮响应方法:(-IBAction)click(id)sender,当点击此按钮的时候程序就会crash掉,因为这个方法已经不存在了,自然会bad access。

4.有时候常常需要找到一个view的控制器。怎么办,其实从官方API中也是可以找到的。API解释:UIViewController is part of your application’s controller layer,

a view controller is responsible for coordinating interactions between your application’s visual presentation (your custom views) and your application’s data model (your custom objects). A view controller is also responsible for handling changes to the views that comprise its view layer.(视图控制器是应用的控制器层的一部分,一个视图控制器视图层和数据层交互时的响应者,一个视图控制器也能响应视图层中的响应控制)这个自然就找到方法如下,这里view是当前的视图:

UIResponder* nextResponder = [view nextResponder];  

if ([nextResponder isKindOfClass:[UIViewController class]]) {  

return (UIViewController*)nextResponder;  

以上都是viewController使用过程中容易出错的地方,希望总结完了,让自己能更深一步的理解,同时也能给广大需要的朋友一些启发吧!


UINavigationController使用详解

UINavigationController是IOS编程中比较常用的一种容器view controller,很多系统的控件(如UIImagePickerViewController)以及很多有名的APP中(如qq,系统相册等)都有用到。说是使用详解,其实我只会介绍几个自认为比较重要或者容易放错的地方进行讲解,下面让我们挨个探探究竟:

首先上一张图(来自苹果官方文档):



1、navigationItem

我们都知道navigationItem是UIViewController的一个属性,这个属性是为UINavigationController服务的。文档中是这么解释的“The navigation item used to represent the view controller in a parent’s navigation bar. (read-only)”,即navigation item在navigation Bar代表一个viewController,具体一点儿来说就是每一个加到navigationController的viewController都会有一个对应的navigationItem,该对象由viewController以懒加载的方式创建,稍后我们可以在对象中堆navigationItem进行配置,可以设置leftBarButtonItem, rightBarButtonItem, backBarButtonItem, title以及prompt等属性。前三个每一个都是一个UIBarButtonItem对象,最后两个属性是一个NSString类型描述,注意添加该描述以后NavigationBar的高度会增加30,总的高度会变成74(不管当前方向是Portrait还是Landscape,此模式下navgationbar都使用高度44加上prompt30的方式进行显示)。当然如果觉得只是设置文字的title不够爽,你还可以通过titleview属性指定一个定制的titleview,这样你就可以随心所欲了,当然注意指定的titleview的frame大小,不要显示出界。

举个简单的例子:

// set rightItem
UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithTitle:@"Root" style:UIBarButtonItemStyleBordered target:self action:@selector(popToRootVC)];
childOne.navigationItem.rightBarButtonItem = rightItem;
[rightItem release];
    
// when you design a prompt for navigationbar, the hiehgt of navigationbar will becaome 74, ignore the orientation
childOne.navigationItem.prompt = @"Hello, im the prompt";

这段代码设置了navigationItem的rightBarButtonItem,同时设置了prompt信息。

2、titleTextAttributes(ios5.0以后可用)

这是UINavigationBar的一个属性,通过它你可以设置title部分的字体,这个属性定义如下:

/* You may specify the font, text color, text shadow color, and text shadow offset for the title in the text attributes dictionary, using the keys found in UIStringDrawing.h.
 */
@property(nonatomic,copy) NSDictionary *titleTextAttributes __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0) UI_APPEARANCE_SELECTOR;

它的dictionary的key定义以及其对应的value类型如下:

//    Keys for Text Attributes Dictionaries
//    NSString *const UITextAttributeFont;                       value: UIFont
//    NSString *const UITextAttributeTextColor;                 value: UIColor
//    NSString *const UITextAttributeTextShadowColor;       value: UIColor
//    NSString *const UITextAttributeTextShadowOffset;      value: NSValue wrapping a UIOffset struct.

下面看一个简单的例子:

NSDictionary *dict = [NSDictionary dictionaryWithObject:[UIColor yellowColor] forKey:UITextAttributeTextColor];
childOne.navigationController.navigationBar.titleTextAttributes = dict;

这个例子就是设置title的字体颜色为黄色,怎么样简单吧。

3、wantsFullScreenLayout

viewController的一个属性,这个属性默认值是NO,如果设置为YES的话,如果statusbar,navigationbar, toolbar是半透明的话,viewController的view就会缩放延伸到它们下面,但注意一点儿tabBar不在范围内,即无论该属性是否为YES,view都不会覆盖到tabbar的下方。

4、navigationBar中的stack

这个属性可以算是UINavigationController的灵魂之一,它维护了一个和UINavigationController中viewControllers对应的navigationItem的stack,该stack用于负责navigationbar的刷新。“注意:如果navigationbar中navigationItem的stack和对应的NavigationController中viewController的stack是一一对应的关系,如果两个stack不同步就会抛出异常。

下面举个简单抛出异常的例子:

SvNavChildViewController *childOne = [[SvNavChildViewController alloc] initWithTitle:@"First" content:@"1"];
[self.navigationController pushViewController:childOne animated:NO];
[childOne release];
    
// raise exception when the stack of navigationbar and navigationController was not correspond
[self.navigationController.navigationBar popNavigationItemAnimated:NO];

当pushViewcontroller的之后,强制把navigationBar中的navigationItem pop一个出去,程序立马挂起。当然这纯粹只是为了验证问题,我想一般的码农没有人会这么写的。


5、navigationBar的刷新

  通过前面介绍的内容,我们知道navigationBar中包含了这几个重要组成部分:leftBarButtonItem, rightBarButtonItem, backBarButtonItem, title。当一个view controller添加到navigationController以后,navigationBar的显示遵循一下几个原则:

  1)、Left side of the navigationBar

  a)如果当前的viewController设置了leftBarButtonItem,则显示当前VC所自带的leftBarButtonItem。

  b)如果当前的viewController没有设置leftBarButtonItem,且当前VC不是rootVC的时候,则显示前一层VC的backBarButtonItem。如果前一层的VC没有显示的指定backBarButtonItem的话,系统将会根据前一层VC的title属性自动生成一个back按钮,并显示出来。

  c)如果当前的viewController没有设置leftBarButtonItem,且当前VC已是rootVC的时候,左边将不显示任何东西。

  此处注意:5.0中新增加了一个属性leftItemsSupplementBackButton,通过指定该属性为YES,可以让leftBarButtonItem和backBarButtonItem同时显示,其中leftBarButtonItem显示在backBarButtonItem的右边。

  2)、title部分

  a)如果当前VC通过 .navigationItem.titleView指定了自定义的titleView,系统将会显示指定的titleView,此处要注意自定义titleView的高度不要超过navigationBar的高度,否则会显示出界。

  b)如果当前VC没有指定titleView,系统则会根据当前VC的title或者当前VC的navigationItem.title的内容创建一个UILabel并显示,其中如果指定了navigationItem.title的话,则优先显示navigationItem.title的内容。

  3)、Right side of the navigationBar

  a)如果当前VC指定了rightBarButtonItem的话,则显示指定的内容。

  b)如果当前VC没有指定rightBarButtonItem的话,则不显示任何东西。

6、Toolbar

navigationController自带了一个工具栏,通过设置 self.navigationController.toolbarHidden = NO来显示工具栏,工具栏中的内容可以通过viewController的toolbarItems来设置,显示的顺序和设置的NSArray中存放的顺序一致,其中每一个数据都一个UIBarButtonItem对象,可以使用系统提供的很多常用风格的对象,也可以根据需求进行自定义。

设置Toolbar内容的例子:

// test ToolBar
UIBarButtonItem *one = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:nil action:nil];
UIBarButtonItem *two = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:nil action:nil];
UIBarButtonItem *three = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:nil action:nil];
UIBarButtonItem *four = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:nil action:nil];
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[childOne setToolbarItems:[NSArray arrayWithObjects:flexItem, one, flexItem, two, flexItem, three, flexItem, four, flexItem, nil]];
[one release];
[two release];
[three release];
[four release];
[flexItem release];
    
childOne.navigationController.toolbarHidden = NO;




7、UINavigationControllerDelegate

这个代理真的很简单,就是当一个viewController要显示的时候通知一下外面,给你一个机会进行设置,包含如下两个函数:

// Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;


当你需要对某些将要显示的viewController进行修改的话,可实现该代理。

8、UINavigationController的viewControllers属性

通过该属性我们可以实现一次性替换整个navigationController的层次, 这个过程如果通过setViewControllers:animated:来设置,并指定动画为YES的画,动画将会从当前的navigationController所显示的vc跳转到所设置的目标viewController的最顶层的那个VC,而中间其他的VC将会被直接从VC层级中移除和添加进来(没有动画)。

9、topViewController Vs visibleViewController

topViewController代表当前navigation栈中最上层的VC,而visibleViewController代表当前可见的VC,它可能是topViewController,也可能是当前topViewController present出来的VC。因此UINavigationController的这两个属性通常情况下是一样,但也有可能不同。

本文来源:http://www.bbyears.com/shoujikaifa/82686.html

热门标签

更多>>

本类排行