要求:1、从基于Xcode空项目模板开始
实现方法分析
1、根据MVC模式,iphone的程序都是有 view-model-controller 组成的。所以,在两个页面就是两个视图控制器和其管理的View。因此:
第一页定义为:cityViewController
第二页定义为:CityDetailViewController
导航控制器在这两个视图控制器之间切换!工程项目名称为:lvyou
2、开发步骤:
第一步:创建一个工程项目。项目名称:lvyou、基于空模板(Windows-based Application)
第二步:创建cityViewController视图控制器。
>>请选择File > New File。在New File窗口中,请选择Cocoa Touch Classes,然后选择UIViewController-subclass。同时,请勾选Options区域中标题为With XIB for user interface的选择框。为文件起个名字,本例视图控制器名称为cityViewController,(类名称习惯以一个大写字母开头)。请务必创建.m和.h文件,并将二者都添加到工程。此时,系统已经生成三个文件(*.h、*.m、*.xib), 实际实现了四项任务:
1)系统为你创建了一个视图控制器(名叫File’sOwner对象),类名为cityViewController
2)系统也为你创建了一个视图view(点*.xib上打开)
3)在视图控制器类上,系统也为你定义了一个输出口IBOulet变量view
4)这个变量(输出口IBOulet变量view)已经关联了视图view
第三步:同样方法创建CityDetailViewController
>>请选择File > New File。在New File窗口中,请选择Cocoa Touch Classes,然后选择UIViewController-subclass。同时,请勾选Options区域中标题为With XIB for user interface的选择框。为文件起个名字,视图控制器名称为CityDetailViewController
第四步:添加(注册)一个导航控制器。
(注册cityViewController是第一个要显示视图控制器)只能用代码方法!(当然,如果你创建工程项目时选择“基于导航的应用”。就会为你自动创建一个名为RootViewController的根视图控制器,并自动生成了一些代码,比如把导航控制器的视图放到窗口的视图内)
方法:在lvyouAppDelegate.h上声明(添加)一个UINavigationController类对象
- //lvyouAppDelegate.h原代码开始
- #import <UIKit/UIKit.h>
- @interface lvyouAppDelegate : NSObject <UIApplicationDelegate> {
- UIWindow *window;
- UINavigationController *navController;//此行新加,对应的实现文件.m上必须要有代码!
- UITabBarController *tabBarController; // 声明一个标签控制器,下一节讲
- }
- @property (nonatomic, retain) IBOutlet UIWindow *window;
- @end
- //lvyouAppDelegate.h原代码结束
- //lvyouAppDelegate.m原代码开始
- #import "lvyouAppDelegate.h"
- #import "cityViewController.h"//此处要加上
- #import "MeiShiTianDi.h"
- @implementation lvyouAppDelegate
- @synthesize window;
- #pragma mark -
- #pragma mark Application lifecycle
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- tabBarController = [[UITabBarController alloc] init];//初始化标签栏控制器
- MeiShiTianDi *viewController =[[MeiShiTianDi alloc] init];//初始化控制器
- viewController.title=@"美食天地";
- navController = [[UINavigationController alloc] init];//初始化导航控制器
- //加入标签栏控制器的控制器数量矩阵
- tabBarController.viewControllers =
- [NSArray arrayWithObjects:navController, viewController,nil];
- [viewController release];
- //定义名称为“所有城市”的返回按钮。该按钮无需target和action
- //因为系统已经实现了返回功能。Style是显示风格
- UIBarButtonItem *backButton =
- [[UIBarButtonItem alloc] initWithTitle:@"所有城市"
- style:UIBarButtonItemStyleBordered
- target:nil action:nil];
- //设置启动应用时第一个要显示的视图控制器,这里是cityViewContrl
- cityViewController *cityViewContrl = [[cityViewController alloc] init];
- cityViewContrl.title = @"旅游指南";//设置第一个视图控制器的标题
- //设置返回按钮
- cityViewContrl.navigationItem.backBarButtonItem= backButton;
- [backButton release];
- //把第一个视图控制器推push到堆栈中
- [navController pushViewController:cityViewContrl animated:NO];
- //这里假定是导航栏的第一个视图,所以animated:NO不要动画化。
- [cityViewContrl release];
- //把导航(标签栏)控制器放到Window下
- //[window addSubview:navController.view];
- [window addSubview:tabBarController.view];
- // Override point for customization after application launch.
- [window makeKeyAndVisible];
- return YES;
- }
- - (void)applicationWillResignActive:(UIApplication *)application {
- }
- - (void)applicationDidEnterBackground:(UIApplication *)application {
- }
- - (void)applicationWillEnterForeground:(UIApplication *)application {
- }
- - (void)applicationDidBecomeActive:(UIApplication *)application {
- }
- - (void)applicationWillTerminate:(UIApplication *)application {
- }
- #pragma mark -
- #pragma mark Memory management
- - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
- }
- - (void)dealloc {
- [tabBarController release];//释放内存
- [navController release];
- [window release];
- [super dealloc];
- }
- @end
- //lvyouAppDelegate.m原代码结束
第五步:设计完善cityViewController视图控制器。
首先在cityViewController.xib上添加一个按钮,修改按钮标题为“北京”。在cityViewController.h中声明一个方法selectCity。将按钮与方法建立连接!
- //cityViewController.h原代码开始
- #import <UIKit/UIKit.h>
- @interface cityViewController : UIViewController {
- }
- - (IBAction) selectCity : (id) sender;//自定义一个方法,点击“北京”按钮,进入下一页
- @end
- //cityViewController.h原代码结束
- //cityViewController.m原代码开始
- #import "cityViewController.h"
- #import "CityDetailViewController.h"//新加上的,声明注册CityDetailViewController
- @implementation cityViewController //定义属性
- //实现自定义的方法(函数)
- -(IBAction) selectCity : (id) sender{
- CityDetailViewController *cityDetailContrl
- = [[CityDetailViewController alloc] init];//初始化CityDetailViewController
- cityDetailContrl.title = @ "北京欢迎您";//设置第二个视图控制器标题
- cityDetailContrl.city = @"北京";//设置要传到下一个控制器的数据——北京
- //把第二视图控制器推入堆栈中
- [self.navigationController pushViewController:cityDetailContrl animated:YES];
- [cityDetailContrl release];//释放内存
- }
- // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- - (void)viewDidLoad {
- //创建一个有边框的文体按钮,按下后,调用视图控制器上的discount方法
- UIBarButtonItem *discountButton = [[UIBarButtonItem alloc]
- initWithTitle:@"折扣信息" style:UIBarButtonItemStyleBordered
- target:self action:@selector(discount:)];
- self.navigationItem.leftBarButtonItem = discountButton;//设置为左边按钮
- [discountButton release];//释放内存
- //设置视图控制器在标签栏上的标题和图像
- // 文字是:旅游指南。图像是:GoldenGateBridge.png
- UITabBarItem *item = [[UITabBarItem alloc]
- initWithTitle:@"旅游指南"
- //initWithTabBarSystemItem:UITabBarSystemItemBookmarks
- image:[UIImage imageNamed:@"GoldenGateBridge.png"]
- tag:0];
- self.tabBarItem = item;
- [item release];
- [super viewDidLoad];
- }
- - (void)didReceiveMemoryWarning {
- // Releases the view if it doesn't have a superview.
- [super didReceiveMemoryWarning];
- // Release any cached data, images, etc that aren't in use.
- }
- - (void)viewDidUnload {
- [super viewDidUnload];
- // Release any retained subviews of the main view.
- // e.g. self.myOutlet = nil;
- }
- - (void)dealloc {
- [super dealloc];
- }
- @end
- //cityViewController.m原代码结束
第六步:设计完善CityDetailViewController
首先在CityDetailViewController
- //CityDetailViewController.h原代码开始
- #import <UIKit/UIKit.h>
- @interface CityDetailViewController : UIViewController {
- IBOutlet UILabel *cityName;// 第二个标签Label创建接口IBOutlet
- NSString *city; //创建一个属性
- }
- @property (copy) NSString *city; //创建一个属性set/get方法
- @end
- //CityDetailViewController.h原代码结束
- //CityDetailViewController.m原代码开始
- #import "CityDetailViewController.h"
- @implementation CityDetailViewController //实现控制器类
- @synthesize city; //属性city变量
- // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- - (void)viewDidLoad {
- cityName.text = city;//获取从前一个页面传来的数据
- //创建一个系统添加按钮,按下后,调用视图控制器上的add方法
- UIBarButtonItem *rightButton = [[UIBarButtonItem alloc]
- initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
- target:self action:@selector(add:)];// 调用视图控制器上的add方法
- //设置为导航控制器控制条上的右边按钮
- self.navigationItem.rightBarButtonItem = rightButton;
- [rightButton release];
- [super viewDidLoad];
- }
- - (void)didReceiveMemoryWarning {
- // Releases the view if it doesn't have a superview.
- [super didReceiveMemoryWarning];
- // Release any cached data, images, etc that aren't in use.
- }
- - (void)viewDidUnload {
- [super viewDidUnload];
- // Release any retained subviews of the main view.
- // e.g. self.myOutlet = nil;
- }
- - (void)dealloc {
- [super dealloc];
- }
- @end
- //CityDetailViewController.m原代码结束
-
第七步:UINavigationItem和UIBarButtonItem
通常每个(指任何)视图控制器都可以定义一个UINavigationItem。UINavigationItem类就是实现这些功能的,这个类包含了如下表:
左边按钮
标题视图
右边按钮
leftBarButtonItem
titleView
rightBarButtonItem
当它所属的视图控制器在导航控制器所控制的堆栈顶部时,即调用(也就是说该视图控制器即将要显示时),系统自动显示该视图控制器的UINavigationItem,开发人员无需编写任何代码来调用UINavigationItem,但之前必须要设置好。上面程序代码中已经有定制好的导航栏左右按钮,简述说明如下:
定制返回按钮:在缺省情况下,下一页上的返回按钮上的文字是上一页的标题,可以在程序中修改为其它文字,要记住!返回按钮是放在上一页的视图控制器上的,所以必须在上一页对应的视图控制器的实现文件(*.m)中去修改。如在上面lvyouAppDelegate.m中有如下代码:(图中绿色代码部分)
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- ……
- navController = [[UINavigationController alloc] init];//初始化导航控制器
- //定义名称为“所有城市”的返回按钮。该按钮无需target和action
- //因为系统已经实现了返回功能。Style是显示风格
- UIBarButtonItem *backButton =
- [[UIBarButtonItem alloc] initWithTitle:@"所有城市"
- style:UIBarButtonItemStyleBordered
- target:nil action:nil];
- //设置启动应用时第一个要显示的视图控制器,这里是cityViewContrl
- cityViewController *cityViewContrl = [[cityViewController alloc] init];
- cityViewContrl.title = @"旅游指南";//设置第一个视图控制器的标题
- //设置返回按钮
- cityViewContrl.navigationItem.backBarButtonItem= backButton;
- [backButton release];
- //把第一个视图控制器推push到堆栈中
- [navController pushViewController:cityViewContrl animated:NO];
- [cityViewContrl release];
- //把导航(标签栏)控制器放到Window下
- //[window addSubview:navController.view];
- [window addSubview:tabBarController.view];
- // Override point for customization after application launch.
- [window makeKeyAndVisible];
- return YES;
- }
在导航控制栏上添加系统按钮和左右按钮。
首先在第一页的导航栏上添加一个“折扣信息”按钮,如在上面所述,要记住!返回按钮是放在上一页的视图控制器上的,所以必须在上一页对应的视图控制器的实现文件(*.m)中去修改。这里要求在第一页的导航栏上添加一个“折扣信息”按钮(显然,这不是返回上一页按钮,而是在导航控制栏上添加一个“左按钮”),故可在当前视图控制器的实现文件(*.m)中去修改,即cityViewController.m中去修改,在它原代码中有如下代码:(图中绿色代码部分)
- - (void)viewDidLoad {
- //创建一个有边框的文体按钮,按下后,调用视图控制器上的discount方法
- UIBarButtonItem *discountButton = [[UIBarButtonItem alloc]
- initWithTitle:@"折扣信息" style:UIBarButtonItemStyleBordered
- target:self action:@selector(discount:)];
- self.navigationItem.leftBarButtonItem = discountButton;//设置为左边按钮
- [discountButton release];//释放内存
- UITabBarItem *item = [[UITabBarItem alloc]
- initWithTitle:@"旅游指南"
- //initWithTabBarSystemItem:UITabBarSystemItemBookmarks
- image:[UIImage imageNamed:@"GoldenGateBridge.png"]
- tag:0];
- self.tabBarItem = item;
- [item release];
- [super viewDidLoad];
- }
其次在第二页的导航栏上添加一个“系统按钮”(右边按钮),根据上面分析,这同样不以至于返回按钮,故可在当前视图控制器的实现文件(*.m)中去修改,即CityDetailViewController.m中去修改,在它原代码中有如下代码:(图中绿色代码部分)
- - (void)viewDidLoad {
- cityName.text = city;//获取从前一个页面传来的数据
- //创建一个系统添加按钮,按下后,调用视图控制器上的add方法
- UIBarButtonItem *rightButton = [[UIBarButtonItem alloc]
- initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
- target:self action:@selector(add:)];// 调用视图控制器上的add方法
- //设置为导航控制器控制条上的右边按钮
- self.navigationItem.rightBarButtonItem = rightButton;
- [rightButton release];
- [super viewDidLoad];
- }
第八步:标签栏控制器(UITabBarController)
标签栏控制器是用数组来管理所控制的视图控制器。这些被管理的视图控制器即可以是导航控制器,也可以是一般的视图控制器。另外,这些视图控制器之间是平等关系,而不像导航控制器所管理的视图控制器之间是所谓的“上下级关系”。缺省情况下,标签栏上显示的是各个视图的标题,如下图显示了五个标签。
iPhone OS的标签栏最多可显示五个标签
当你选择某一个视图控制器时,该视图控制器就执行。当你选择另一个视图控制器时,当前视图控制器的状态被保留。非常类似微软中的多窗口的概念。
关系:
平等关系 上、下级之间关系 标签栏控制器
UITabBarController
导航控制器
(旅游信息)
一般视图控制器
cityViewController
一般视图控制器
CityDetailViewController
一般视图控制器
(美食天地)
MeiShiTianDi
下面我们将创建一个标签栏控制器,如上表,它有两个标签“旅游信息”和“美食天地”。“旅游信息”由于前面已经完成,它管理着两个视图控制器(cityViewController、 CityDetailViewController
),因此,下面重点讲解未完成的工件。 1、项目的委托AppDelegate声明注册一个标签控制器、初始化后放到主窗口Window下
首先:因为项目名称仍然是lvyou,所以要在项目.h中(lvyouAppDelegate.h)声明一个标签控制器:
- //lvyouAppDelegate.h原代码开始
- #import <UIKit/UIKit.h>
- @interface lvyouAppDelegate : NSObject <UIApplicationDelegate> {
- UIWindow *window;
- UINavigationController *navController;//此行新加,对应的实现文件.m上必须要有代码!
- UITabBarController *tabBarController;// 声明一个标签控制器
- }
- @property (nonatomic, retain) IBOutlet UIWindow *window;
- @end
- //lvyouAppDelegate.h原代码结束
- 其次:要在项目.m中(lvyouAppDelegate.m)初始化,并将所要管理的控制器(本例是两个:一个导航控制器、另一个是美食天地视图控制器)放到其viewControllers数组中
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- tabBarController = [[UITabBarController alloc] init];//初始化标签栏控制器
- MeiShiTianDi *viewController =[[MeiShiTianDi alloc] init];//初始化控制器
- viewController.title=@"美食天地";
- navController = [[UINavigationController alloc] init];//初始化导航控制器
- //加入标签栏控制器的控制器数量矩阵
- //本例为两个控制器navController viewController
- tabBarController.viewControllers =
- [NSArray arrayWithObjects:navController, viewController,nil];
- [viewController release];//因它不是第一个视图控制器,故释放内存
- //定义名称为“所有城市”的返回按钮。该按钮无需target和action
- //因为系统已经实现了返回功能。Style是显示风格
- UIBarButtonItem *backButton =
- [[UIBarButtonItem alloc] initWithTitle:@"所有城市"
- style:UIBarButtonItemStyleBordered
- target:nil action:nil];
- //设置启动应用时第一个要显示的视图控制器,这里是cityViewContrl
- cityViewController *cityViewContrl = [[cityViewController alloc] init];
- cityViewContrl.title = @"旅游指南";//设置第一个视图控制器的标题
- //设置返回按钮
- cityViewContrl.navigationItem.backBarButtonItem= backButton;
- [backButton release];
- //把第一个视图控制器推push到堆栈中
- [navController pushViewController:cityViewContrl animated:NO];
- //这里假定是导航栏的第一个视图,所以animated:NO不要动画化。
- [cityViewContrl release];
- //把导航(标签栏)控制器放到Window下
- //[window addSubview:navController.view];
- [window addSubview:tabBarController.view]; //把标签栏控制器放到Window下
- // Override point for customization after application launch.
- [window makeKeyAndVisible];
- return YES;
- }
2、创建另一个(第三个)视图控制器——美食天地:MeiShiTianDi
方法同前:
>>请选择File > New File。在New File窗口中,请选择Cocoa Touch Classes,然后选择UIViewController-subclass。同时,请勾选Options区域中标题为With XIB for user interface的选择框。为文件起个名字,视图控制器名称为MeiShiTianDi。此时,系统已经生成三个文件(*.h、*.m、*.xib),在新的视图控制器的视图上(MeiShiTianDi.xib)添加一些按钮(加四个,命名为“广东菜、浙江菜、四川菜、东北菜”)。
1)、添加标签栏控制器的属性到lvyouAppDelegate.h中——(上一步已经完成!)
2)、在lvyouAppDelegate.m文件中的- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOp
tions:(NSDictionary *)launchOptions 方法中,用代码方式创建一个标签栏控制器,并初始化它,最后将两个控制器navController(旅游信息)、viewController(美食天地)放在标签控制器上。——(上一步已经完成!) - //MeiShiTianDi.h原代码开始
- #import <UIKit/UIKit.h>
- @interface MeiShiTianDi : UIViewController {
- }
- @end
- //MeiShiTianDi.m原代码结束
- //MeiShiTianDi.h原代码开始
- #import "MeiShiTianDi.h"
- @implementation MeiShiTianDi
- // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- - (void)viewDidLoad {
- //UIImage *tabImage = [UIImage imageNamed:@"shrimp.jpg"];
- //设置视图控制器在标签栏上的标题和图像
- // 文字是:美食天地。图像是:UITabBarSystemItemBookmarks
- UITabBarItem *item = [[UITabBarItem alloc]
- initWithTitle:@"美食天地"
- initWithTabBarSystemItem:UITabBarSystemItemBookmarks
- //image:tabImage
- tag:0];
- //本例还注释掉了使用自己的图像shrimp.jpg的两行代码。如你交换一下也能运行
- self.tabBarItem = item;
- [item release];
- [super viewDidLoad];
- }
- - (void)didReceiveMemoryWarning {
- // Releases the view if it doesn't have a superview.
- [super didReceiveMemoryWarning];
- // Release any cached data, images, etc that aren't in use.
- }
- - (void)viewDidUnload {
- [super viewDidUnload];
- // Release any retained subviews of the main view.
- // e.g. self.myOutlet = nil;
- }
- - (void)dealloc {
- [super dealloc];
- }
- @end
- //MeiShiTianDi.m原代码结束
3)、设置视图控制器在标签栏上的标题和图像(UITabBarItem)
每个视图控制器类都有一个UITabBarItem。通过这个类,可以设置视图控制器在标签栏上的标题和图像。标题和图像分为两个类,一类是自己的图像和文字(格式为.png);另一类是系统提供的图像和文字。
首先添加图像到项目中,(在资源文件夹下)
添加UITabBarItem代码到cityViewController.m的viewDidLoad方法下,这里使用用户自己的图像,图像名是:GoldenGateBridge.png
- - (void)viewDidLoad {
- //创建一个有边框的文体按钮,按下后,调用视图控制器上的discount方法
- UIBarButtonItem *discountButton = [[UIBarButtonItem alloc]
- initWithTitle:@"折扣信息" style:UIBarButtonItemStyleBordered
- target:self action:@selector(discount:)];
- self.navigationItem.leftBarButtonItem = discountButton;//设置为左边按钮
- [discountButton release];//释放内存
- //设置视图控制器在标签栏上的标题和图像
- // 文字是:旅游指南。图像是:GoldenGateBridge.png
- UITabBarItem *item = [[UITabBarItem alloc]
- initWithTitle:@"旅游指南"
- //initWithTabBarSystemItem:UITabBarSystemItemBookmarks
- image:[UIImage imageNamed:@"GoldenGateBridge.png"]
- tag:0];
- self.tabBarItem = item;
- [item release];
- [super viewDidLoad];
- }
添加UITabBarItem代码到MeiShiTianDi.m的viewDidLoad方法下,这里使用系统提供的图像,图像名是:UITabBarSystemItemBookma
rks,当然,本例还注释掉了使用用户自己的图像的两行代码。如果你交换一下,也能运行。 - - (void)viewDidLoad {
- //UIImage *tabImage = [UIImage imageNamed:@"shrimp.jpg"];
- //设置视图控制器在标签栏上的标题和图像
- // 文字是:美食天地。图像是:UITabBarSystemItemBookmarks
- UITabBarItem *item = [[UITabBarItem alloc]
- initWithTitle:@"美食天地"
- initWithTabBarSystemItem:UITabBarSystemItemBookmarks
- //image:tabImage
- tag:0];
- //本例还注释掉了使用用户自己的图像shrimp.jpg的两行代码。如你交换一下也能运行
- self.tabBarItem = item;
- [item release];
- [super viewDidLoad];
- }