基于window-based模板的多View程序

来源:互联网 发布:超星网络课程答案 编辑:程序博客网 时间:2024/05/16 05:26

去我的目录

上礼拜一直忙,没有空写blog了。。不过凡事都要坚持才能有点儿效果。
看着阅读数量的增加,表明还是有人在看我的blog,这就是我坚持的动力,呵呵。
先贴一则新闻:http://it.sohu.com/20090711/n265142243.shtml
iPhone真的要进入国内市场了么?

<script type="text/javascript"><!-- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));// --></script><script type="text/javascript"><!-- google_ad_client = "pub-8097737732457645";/* 728x90, 创建于 09-6-23 */google_ad_slot = "0915066646";google_ad_width = 728;google_ad_height = 90;// --></script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>今天我们来看一看如何基于window-based模板来创建一个多View的程序。之前我们提到过,iPhone程序一定是一个单window多 View的程序,而平常我们也经常看到用户轻轻将手指刷过屏幕,就会有新的页面显示出来,这就是多个View之间的转换。那么,是如何实现的呢?我们开始吧!

启动xCode,File->New Project->选择window-based模板,我们这次创建的程序起名为FoodList。


首先,我们来分析一下多View程序应该是怎么样的一个框架:
前面介绍过,iPhone程序的设计是按照MVC(Model-View-Control)的模式进行的。一般来说,每一个页面(View)都会有一个Controller对应(这个Controller就是我们实现的基于UIViewController的类),用于控制这个View和用户的交互。但是在设计多View程序的时候,我们还需要一个Controller用于负责不同View之间的转换。也就是说,如果程序有2个View,他们之间要互相转换,那么它必须包括至少3个xib文件(MainWindow.xib(这个是默认有的)和表示这两个View的xib文件),同时,还至少要有 3个Controller(2个用于控制View,另外一个用于控制View之间的转换)。

今天我们要完成的程序是:首先现实一个欢迎页面,然后用户点击按钮之后,进入下一个页面,是一个食物的列表。

1)选中Classes文件夹,右键,Add->New File,选择Cocoa Touch Classes中的UIViewController,取名为SwitchViewController,从名字也能猜到这个类的用途:控制View之间的转换。
2)重复上面的步骤:添加WelcomeController和FoodListController。
3)选中Resources文件夹,右键,Add->New File,选择User Interfaces中的View XIB。取名为WelcomeView。
4)重复3),添加FoodListView。
5)双击MainWindow.xib,启动Interface Builder,然后从控件库中找到View Controller,拖到MainWindow.xib的窗口中。如图所示:
add view controller

6)选中新添加的View Controller,组合键cmd(苹果的功能键)+4,在Class Identity下方,将Class名称改为SwitchViewController。这样,我们就将这个新添加的控件和代码(SwitchViewController类)联系起来了。保存。

 

下面开始代码部分。
在FoodListAppDelegate.h中:
@class SwitchViewController;
@interface FoodListAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    SwitchViewController *viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet SwitchViewController *viewController;

@end


设计多view程序时,一定要有一个父View。在多view转换的时候,实际上是把一个view从父view中删除,然后将另一个view加入父view的过程。这里的父view就是我们的SwitchViewController的view(什么?SwitchViewController中怎么会有view,参考前一篇blog :) )。

在FoodListAppDelegate.m中:
#import "FoodListAppDelegate.h"
#import "SwitchViewController.h"

@implementation FoodListAppDelegate

@synthesize window;
@synthesize viewController;

- (void)applicationDidFinishLaunching:(UIApplication *)application {   
    [window addSubview:viewController.view];
    // Override point for customization after application launch
    [window makeKeyAndVisible];
}
- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}


同样,参见之前的文章(注:在以后的blog中,我也会注意减少这样的代码的出现次数,以保证我们能将篇幅集中在重要的问题上,读者可以参考以前的文章来了解这些基本知识)。

在SwitchViewController.h中:
#import <UIKit/UIKit.h>

@class WelcomeController;
@class FoodListController;


@interface SwitchViewController : UIViewController {
    WelcomeController *welcomeController;
    FoodListController *foodlistController;

}

@property (nonatomic, retain) WelcomeController *welcomeController;
@property (nonatomic, retain) FoodListController *foodlistController;

- (void) switchView;

@end


由于这个类用于控制两个View之间的转换,所以它的两个成员变量就是这两个View的Controller。函数 - (void) switchView就是用于转换view的函数。

在SwitchViewController.m中:
#import "WelcomeController.h"
#import "FoodListController.h"


@implementation SwitchViewController

@synthesize welcomeController;
@synthesize foodlistController;


... ...

- (void)viewDidLoad {
    WelcomeController *wc = [[WelcomeController alloc] initWithNibName:@"WelcomeView" bundle:nil];
    self.welcomeController = wc;
    [wc release];
   
    [self.view insertSubview:self.welcomeController.view atIndex:0];

    [super viewDidLoad];
}
- (void) switchView {
    if( self.foodlistController == nil ) {
        FoodListController *fc = [[FoodListController alloc] initWithNibName:@"FoodListView" bundle:nil];
        self.foodlistController = fc;
        [fc release];
    }
    if( self.welcomeController.view.superview != nil ) {
        [welcomeController.view removeFromSuperview];
        [self.view insertSubview:foodlistController.view atIndex:0];
    }
    else {
        [foodlistController.view removeFromSuperview];
        [self.view insertSubview:welcomeController.view atIndex:0];
    }
}

... ...

- (void)dealloc {
    [welcomeController release];
    [foodlistController release];

    [super dealloc];
}

下面我们来仔细看看这些代码:

1)首先来看看viewDidLoad,这个函数是在SwitchViewController的资源装载完毕后被自动调用的,在这个函数里面我们干了两件事情:
第一,从资源文件中装载了WelcomeView.xib,将它赋值给welcomeController;
第二,将welcomeController的view添加到switchViewController的view中;

我们在FoodListAppDelegate.m中,将viewController的view添加到主窗口中,所以viewController的 view就是我们用于转换不同view的地方。本质上,所谓的转换view,就是将一个view从viewController.view中删除,然后添加入另外一个view。由于我们想显示的第一个view一定是welcome的页面,所以这里就将welcomeController的view添加了进来。

我们在这里并没有装载FoodListView的资源,这是因为用户有可能看完第一个页面以后就退出了程序,所以没有必要在这个时候装载资源,iPhone开发中,把这种策略称为lazy loading。

2)switchView,这是我们实现转换view功能的地方。首先判断是否已经装载了FoodListView,如果还没有的话,就先装载这个资源。然后我们要判断目前显示在页面上的是哪一个view。通过这个语句就可以判断:
if (self.welcomeController.view.superview != nil ) {
}

它的含义是:welcomeController的view是否还有上一级的view呢?因为我们知道,任何一个view都要添加到 viewController的view中才能够显示出来,所以如果这个view目前显示在页面上,那么viewController的view就一定是它的上一级的view;如果这个view目前没有显示在也面上,就没有上一级的view。

转换view分两步:

1)将当前view从上一级的view中剔除: [welcomeController.view removeFromSuperview];
2)添加入新的view:[self.view insertSubview:foodlistController.view atIndex:0];

好了,到这里我们就完成了view转换的功能,下面我们来简单实现一下WelcomeController和FoodListController中的内容。
<script type="text/javascript"><!-- google_ad_client = "pub-8097737732457645";/* 728x90, 创建于 09-6-23 */google_ad_slot = "0915066646";google_ad_width = 728;google_ad_height = 90;// --></script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>
在WelcomeView.xib中添加一个Button,取名为Go to food list,然后在WelcomeController.h中添加一个方法
- (IBAction) switchToFoodList;

在WelcomeController.m中:
#import "WelcomeController.h"
#import "FoodListAppDelegate.h"
#import "SwitchViewController.h"


@implementation WelcomeController
... ...
- (IBAction) switchToFoodList {
    FoodListAppDelegate *application = (FoodListAppDelegate*)[[UIApplication sharedApplication] delegate];
    [application.viewController switchView];
}


这里来解释一下:我们想要调用SwitchViewController中的方法switchView,所以必须包含头文件SwitchViewController.h,而viewController这个对象又是FoodListAppDelegate的成员变量,所以我们要包含FoodListAppDelegate.h。我们通过:
[[UIApplication sharedApplication] delegate] 来得到FoodListAppDelegate类。
delegate 是UIApplication的成员变量,它是一个协议类(UIApplicationDelegate)。由于FoodListAppDelegate 遵守了UIApplicationDelegate协议,所以可以通过类型转换得到FoodListAppDelegate。这样我们就能调用其中的 viewController的 switchView方法了。

在FoodListView.xib中添加一个UILabel和一个Button,取名为Go back。然后在FoodListController.h中添加:

@interface FoodListController : UIViewController {
    IBOutlet UILabel * label;
}
@property (nonatomic, retain) IBOutlet UILabel * label;
- (IBAction) switchToWelcome;


因为我们打算动态的向label中添加一些内容,所以这里我们要得到UILabel的对象。

在FoodListController.m中添加:
#import "FoodListController.h"
#import "FoodListAppDelegate.h"
#import "SwitchViewController.h"


@implementation FoodListController
@synthesize label;

- (void)viewDidLoad {  
     NSString * list = [[NSString alloc] initWithFormat: @"beef/npork/nfish/ntomato/npotato/nsalad/n"];
    label.text = list;
    [list release];

    [super viewDidLoad];
}

- (IBAction) switchToWelcome {
    FoodListAppDelegate *application = (FoodListAppDelegate*)[[UIApplication sharedApplication] delegate];
    [application.viewController switchView];
}


- (void)dealloc {
    [label release];
    [super dealloc];
}


这样我们就完成了所有的工作么?呵呵,还没有。不要忘了,我们还需要使用Interface Builder把控件和代码联系起来。

首先,打开MainWindow.xib,按住ctrl,选中Food List App Delegate,拖动鼠标至Switch View Controller上面,然后松开,选择viewController。这样,我们就把变量viewController和Switch View Controller这个资源联系起来了。
然后,打开WelcomeView.xib,将UIButton的Touch Inside Up事件和函数switchToFoodList联系起来。
最后,打开FoodListView.xib,将UILabel和变量label联系起来,将UIButton的Touch Inside Up事件和函数switchToWelcome联系起来。

好了,编译运行吧:) 你应该能看到:

welcomefood list

<script type="text/javascript"><!-- google_ad_client = "pub-8097737732457645";/* 728x90, 创建于 09-6-23 */google_ad_slot = "0915066646";google_ad_width = 728;google_ad_height = 90;// --></script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>

这就是我们今天的内容。下面我还会针对这个简单的application做一些扩展,包括在view转换的时候加入一些动画效果,使用Table来现实我们的food list等等。

原创粉丝点击