导航控制器
推送添加一个视图控制器
-(void)pushViewController:(UIViewController*)viewController animated:(BOOL)animated;
animated,在过渡时动画的属性,一般设置为NO
移除一个视图控制器
-(UIViewController*)popViewControllerAnimated:(BOOL)animated;
返回值是被弹出的那个视图控制器,当它弹出来,导航控制器会自动release它,因此如果你没有对它的引用,以及一个对于这视图控制器的retain计数在另外某处弹出了,在这个点你会取回一个如果你不坚持用它就会消失的autoreleased对象
设置视图控制器的整个堆栈的改变(iPhone3.0中添加的)
-(void)setViewControllers:(NSArray*)viewControllers animated::(BOOL)animated;
它让你用一个调用就替换整个导航堆栈的内容。
推送你的第一个视图控制器
-(void)applicationDidFinishLaunching{
navController= [ [UINavigationController alloc] init ];
[navControllerpushViewController : firstViewController animated:NO];
//不会出现第一个视图的转换动画firstViewController是UIView的一个子类,自己实现的视图控制器
[window addSubview:navController.view];//把导航控制器的视图作为窗口的子视图
}
//applicationDidFinishLaunching是应用动画出现,但是在它变成可视之前,在屏幕上第一个被调用的事件,它是设置最初始用户界面的好地方,我们首先会去分配新的UINavigationController,这是在代码中实现的,如果你在主穿法口nib中拖拽出一个UINavigationController,那会等同于在这里allocinit一个,当然,你需要从你的应用程序委派中创建一个导航控制器上出口以便你能取得对它的指针。
NavigationController ,只是UIViewController的一个子类,因此它已经有一个视图属性,而且它知道如何给回你一个视图。它实际上管理一个视图,这个视图包含了其他一些被动画的视图,如导航条,标签栏以及你的视图控制器的视图。因此这个给回你的视图实际上包含所有的其他东西。你向NavigationController询问它的视图,然后添加它为视图的一个子视图,这会设置了你的应用程序的基础。
响应用户的操作
在堆栈中推送出一个视图控制器
-(void)someAction:(id) sender {
UIViewController*viewController = ….;
[self.navigationControllerpushViewController : viewController animated : YES];
}
不要直接调用pop函数,当你要移除一个视图时,是通过按返回键来实现的,一般情况下你不需要调用popViewController,但是在少数情况下,你可能会那么做。
例子(具体实例见我的资源):
首先创建一个windowbased的应用程序,命名为PushPop,然后添加一个视图控制器(带有xib文件),命名为FirstViewController。
在firstViewController.xib文件中放入一个按钮,文本为:PushAnother
FirstViewController.h文件:
#import<UIKit/UIKit.h>
@interfaceFirstViewController : UIViewController{
}
-(IBAction)pushViewController:(id)sender;
@end
FirstViewController.m文件中对动作的实现
-(IBAction)pushViewController:(id)sender{//空实现(下面会作修改)}
首先在window上显示我们创建的第一个视图.
在pushPopAppDelegate.h文件中声明UINavigationController的一个变量如下:
UINavigationController* navController;
在pushPopAppDelegate.m文件中的-(void)applicationDidFinishLaunching:(UIApplication*)application中实现推送第一个视图。如下:
-(void)applicationDidFinishLaunching:(UIApplication*)application {
navController= [[UINavigationControlleralloc]init];
FirstViewController*firstViewController = [[FirstViewControlleralloc]init];
firstViewController.title=@"First";/
/设置标题,当进入另一个视图时,该标题会被装入返回键中,作为返回键的标题
[navControllerpushViewController:firstViewControlleranimated:NO];
[firstViewControllerrelease];
[_windowaddSubview:navController.view];
[self.windowmakeKeyAndVisible];
}
注意:在pushPopAppDelegate.m文件中,系统有可能为你显示地实现了-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法,那么你可以将上面方法中的代码放入该方法中,因为在-(void)applicationDidFinishLaunching:(UIApplication*)application方法和-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法同时显示地实现的时候,系统会执行有参数的applicationdidFinishLaunching,也就是(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法,而不会执行-(void)applicationDidFinishLaunching:(UIApplication*)application方法。
我们再添加一个视图控制器,命名为SecondViewController,我们在SecondViewController.xib文件中添加一个标签,文本为iam second.回到FirstViewController.m文件中,在头文件中引入SecondViewController的头文件。并完善按钮的单击功能,如下:
-(IBAction)pushViewController:(id)sender
{
SecondViewController*secondViewController =[[SecondViewControlleralloc]init];
secondViewController.title=@"Second";
[self.navigationControllerpushViewController:secondViewControlleranimated:YES];
[secondViewControllerrelease];
}
运行效果为:
一开始界面: 按下PushAnother键后的效果:
应用程序的数据流
视图之间的数据传递
例如Paparazzi应用程序
分析:
一个屏幕对应一个控制器
第一个列表控制器会取的第二个列表控制器,第一个列表会显示联系人列表,第二个列表会显示联系人的照片列表,最后一个是详细信息的控制器,它会显示详情----实际的图像。
连接视图控制器
首先要清除需要传递数据的对象,然后为你的视图控制器定义输入参数。
例子:
从firstViewController传递数据到SecondViewController
首先在SecondViewController中定义各输入参数属性,并可以存储。如下:
@interfaceSecondViewController : UIViewController{
IBOutletUILabel* textLabel;//指向先前的那个label
NSString*label;
}
@property(copy)NSString*label;
@end
并显示传递过来的数据
-(void)viewDidLoad
{
[superviewDidLoad];
textLabel.text=label;//添加
//Do any additional setup after loading the view from its nib.
}
然后在FirstViewController中实例化SecondViewController时将参数进行传递,如下(背景色为黄色的是后添加的):
-(IBAction)pushViewController:(id)sender
{
staticintcount = 1;
SecondViewController*secondViewController =[[SecondViewControlleralloc]init];
secondViewController.title=@"Second";
secondViewController.label= [NSStringstringWithFormat:@"Pushed%d",count];
count++;
[self.navigationControllerpushViewController:secondViewControlleranimated:YES];
[secondViewControllerrelease];
}
自定义导航栏
可以用定制的按键或控制取定制导航条的外观
UINavigationItem
每个视图控制器都会有一个UINavigationItem,UINavigationItem定义了标题,左键和右键还有可能有一个中心视图以及其它一些在header中见到的东西。
另外一个类UIBarButtonItem,你可以用它去定义左边和右边按钮的外表,还有一些其它属性是在UINavigationBar.h中可以见到。当然,UINavigationItem也是在那里定义的。每一个视图控制器都有一个用来定制的NavigationItem,当那个视图控制器是你的导航堆栈中的顶层视图控制器,它的NavigationItem的内容会自动地在导航条中显示,因此你不需要修改或直接处理UINavigationBar,UINavigationController会做这个
Navigation Item的所属关系:
一个视图控制器有一个NavigationItem,这个NavigationItem有一个leftBarButtonItem,一个标题视图以及一个rightBarButtonItem,你可以使用这三个属性,定义那些在你的导航条中显示的东西。UIViewController实际上已经有一个标题属性,因此尽管UINavigationItem也定义了标题属性,它实际上继承自视图控制器。如果你设置了viewController.title到一些字符串,那会在导航条中显示,你不需要设置NavigationItem的标题,视图控制器会处理好那个,它替你把标题传递到NavigationItem,因此那定义为UIViewController上的property,它是自动被NavigationItem继承。
左键和右键
UIBarButtonItem类
是一个特殊的类,它定义了按键的外观和行为,从它自身来说,它实际上不是UIView的子类,因此UIBarButtonItem不能放进视图层级的任何地方,它只是定义了特别显示在导航栏和工具条中的按键的外观,它能在你的按键中显示字符串或图像或者它还能显示一整群的预定义的系统物件,它还定义了目标和行为,这点与通常的按钮相同。
TextBar Button Item
通常会设置下面情况:
-(void)viewDidLoad
{
UIBarButtonItem*fooButton = [[UIBarButtonItemalloc]initWithTitle:@"Foo"style:UIBarButtonItemStyleBorderedtarget:selfaction:@selector(foo:)];
self.navigationItem.leftBarButtonItem= fooButton;
[fooButtonrelease];
}
效果如图:
Sytem Bar Button Item
例如:
-(void)viewDidLoad
{
UIBarButtonItem*addButton = [[UIBarButtonItemalloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAddtarget:selfaction:@selector(add:)];
self.navigationItem.rightBarButtonItem= addButton;
[addButtonrelease];
[superviewDidLoad];
}
基本上所有的IBarButtonSystemItem都是以IBarButtonSystemItem为文本开头的,然后以一些定制的东西结尾。(本例中是UIBarButtonSystemItemAdd)
效果:
/ Done Button
标准的UIBarButtonItem,那是由所有的视图控制器提供的,它在UITableViewController的情况下最有用,在那里,它已经设置了有表格视图的进入和退出编辑模式。
是一个常见的模式
你能通过在任何视图控制器中调用Self.EditButtonItem取得它,它并不需要是任何特殊的视图控制器,只是UIViewController自身实现了它,例如:self.navigationItem.rightBarButtonItem= Self.EditButtonItem,Self.EditButtonItem返回的类型是UIBarButtonItem。它会自动地在行为中设置一个目标,那个目标会一直是self,行为会一直是“setEditinganimated”,你可以实现这个功能,它会在用户轻按那个编辑按键时被调用。
-(void)setEditing:(BOOL)editinganimated:(BOOL)animated
{
}
CustomTitle View
在头部位置你可以放任意的视图,你能在那里设一个任意的UIViewSubClass,因此你只创建你的UIViewSubClass,然后分配它给那个标题视图,它会显示在你的导航条的中间,代替你的视图控制器的标题。例如:
UISegmentedControl*segmentedController = .....;
self.navigationItem.titleView=segmentedController;
[segmentedControllerrelease];
BackButton
前一个视图控制器的标题会显示在返回键中,如果你的标题非常长,那么这个BackButtonItem就会非常的大。在这里我们就会想设置的标题与前一个视图控制器的标题不同,因此我们会修改它。例如:
self.title=@"hello.............";
UIBarButtonItem*heyButton = [[UIBarButtonItem alloc] initWithTitle:@"hey!"style:UIBarButtonItemStyleBorderedtarget:nilaction:nil];//为nil是为了保持默认行为。
self.navigationItem.backBarButtonItem= heyButton;
[heyButtonrelease];
设置要返回那个视图控制器就在实例化那个视图控制器的地方写入上面的这段代码。如果在一个视图控制器中你既有前一个视图控制器的返回键,又有自己定制的左按键,那么左按键会覆盖掉返回键。
TabBar Controllers
UITabBarController
是试图控制器的集合
标签栏控制器管理其它一个排列的视图控制器,与导航控制器最大的不同是,在后者你会推出它们,而它们是一个堆栈,对于标签栏控制器,它只是一个排列,它在底部的标签栏显示它所管理的这些标签,当用户轻点它们,它会从一个视图切换到另外一个视图,之间没有动画,标签栏的title实际是那个视图控制器的title。你可以在一个特定的UIViewController上还能设置另外一个物件,一个TabBarItem,它定义了用在标题上的图片,尽管那个标题也是视图控制器的标题。你可以像设置NavigationItem一样去设置它,在那里设置属性,然后把图片和标题都显示在那,就像NavigationItem一样,你能在你的标签栏的不同图标中使用很多预定义的系统样式
创建一个TabBar Controller
-(void)applicationDidFinishLaunching:(UIApplication*)application {
tabBarController= [[UITabBarController alloc] init];
tabBarController.viewControllers= myViewControlles;//myViewControlles是NSArray类型
[_windowaddSubview: tabBarController.view];
}
TabBar的外观
在视图控制器中能定义它们在标签栏中的外观
用到的是UIBarButtonItem,UITabBarItem会有标题和图片或者它会是系统物件之一,每个视图控制器都有一个可定制的TabBarItem,你无需去创建它,你只需要调用Self.TabBarItem,然后它会为你创建一个,而且你能分配属性给它。
创建TabBar Items
你可以创建TabBar Items,并且带有标题和图片
-(void)viewDidLoad
{
UITabBarItem*item = [[UITabBarItemalloc]initWithTitle:@"Playlists"image:[UIImageimageNamed:@"Music.png"]tag:0];
self.tabBarItem= item;
[itemrelease];
}
效果:
你也可以使用系统物件,由UIKit提供的预定义物件,例如:
-(void)viewDidLoad
{
UITabBarItem*item = [[UITabBarItemalloc]initWithTabBarSystemItem:UITabBarSystemItemBookmarkstag:0];
self.tabBarItem= item;
[itemrelease];
}
效果:
标签控制器做的另外一个事情是为你提供了在右下角的按键,那就是MoreViewController,如果你在标签栏控制器上设置了一个排列的视图控制器,它无法全部显示在屏幕上,通常你能放置最多5个,它会在最后一个替换成“更多”按键,当你轻点按键,它会为你创建整个表格视图,而且管理全部东西,你不需要做任何额外的事情,它会展示用户所有你设置在排列上的其它视图控制器的列表,并让它们在其中选择,它甚至还支持定制。最后,它实际上能定制显示的顺序,在顶部欧一个编辑键,如果点它,这个新视图会滑出来,它有你在标签栏控制器排列上设置的所有物件的所有图片,用户能拖拽它们并重新排序,通过把另外那些放fao标签栏,这会改变排序,以及它们在标签栏看到的这些功能完全由UITabBarController提供,你只需要拿来用就可以。
将导航栏和标签栏结合在一起使用
创建一个tabbar controller
tabBarController = [[UITabBarController alloc] init];
创建每一个navigationcontroller
navController = [[UINavigationController alloc] init];
[navController pushViewController:firstViewController animated:NO];
将它们添加到tabbar controller
tabBarController.viewControllers = [NSArrayarrayWithObjects:navController,anotherNavController,someViewController,nil];//返回的是autoreleased