学到这里感觉有点难了,其实这篇文章再草稿箱里放了好久了~ 最近对于学习的热情下降了。这不行~抓紧学习走起!


在这一章节的学习中主要针对导航控制器及表视图来建立多视图的应用,

首先要了解一些概念--

1.导航控制器

UINavigationController是用于构建分层应用程序的主要工具,它在管理以及换入和换出多个内容视图方面与UITabBarController较为类似。

两者间的不动之处在于UINavigationController是作为栈来实现,这让他非常适用于处理分层的数据。栈:先进后出,后进先出。

2.控制器栈

根控制器(root view controller) 子控制器(subcontroller)

在设计导航控制器时,需要指定用户看到的第一个视图,该视图处在导航栈的最底层,其对应的控制器称为根控制器.所以不要把根控制器理解为导航控制器.根控制器也是导航控制器的一个子控制器.

在术语上把栈中的除了根控制器其余的控制器称为子控制器.

一般地,根控制器对应的视图上有各个子控制器视图的入口,回退到根视图然后再切换各个子视图.

默认地,导航控制器会自动在当前子控制器对应视图的导航栏的右端加一个返回按钮,名称是上一个视图的标题.

3. 导航按钮.

导航按钮类似于网页上的后退按钮,当点击时,当前的视图控制器出栈,栈中的下一个视图成为当前视图.

4. 其它术语:

扩展图标(accessory icon)称为扩展指示器(disclosure indicator),告知将切换到另一个视图,它以一个灰色箭头表示.

细节展示按钮(detail disclosure button)不仅是一个图标,它还是一个可单击的控件.

实例:

下面将建立一个由6个部分组成的分层应用程序:NavNice

主视图如下:

即有6子控制器

第一个子控制器是展示按钮视图 包含一个细节展示按钮

第二个子控制器是校验表视图 “多选一”的操作

第三个子控制器是行控制视图 在每行的扩展视图中添加了一个可单击的按钮

第四个子控制器是可移动行视图 可以对行进行重新排序

第五个子控制器是可删除行视图 允许删除行的编辑模式

第六个子控制器是可编辑详细信息视图 对详细信息的编辑模式 - 这里的编码可能有点问题~

---------------------------看到只有七个界面,以为会很容易,谁知…--------------------------------

1.首先,建立一个空项目。从零开始。

然后,建立FirstLevelViewController 及 SecondLevelViewController ,

在建文件的同时让它们继承于UITableViewCell,XCode会帮我们自动实现协议抽象方法

现在项目的骨架如下:

2.下一步,在AppDelegate.m中启用委托加载视图

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
//    // Override point for customization after application launch.
//    self.window.backgroundColor = [UIColor whiteColor];
//    [self.window makeKeyAndVisible];
//    return YES;self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];// Override point for customization after application launch.FirstLevelViewController *first = [[FirstLevelViewController alloc] init];UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:first];self.window.rootViewController = navigation;self.window.backgroundColor = [UIColor whiteColor];[self.window makeKeyAndVisible];return YES;
}

3.启动运行,一级页面效果 效果如下: 空空白白就一个tableView

4.接下来要编写第一个子控制器的内容,由于它还嵌套了另一个视图,所以这里先从里到外从详情页写起。

建立DisclosureDetailViewController及DisclosureDetail.xib

DisclosureDetailViewController.h编码

#import <UIKit/UIKit.h>@interface DisclosureDetailViewController : UIViewController
@property (retain, nonatomic) IBOutlet UILabel *label;
@property (copy, nonatomic) NSString *message;@end

DisclosureDetailViewController.m相关编码

@synthesize label;

@synthesize message;

- (void)viewWillAppear:(BOOL)animated;
{[super viewWillAppear:animated];self.label.text = self.message;
}-(void) dealloc
{[label release];[message release];[super dealloc];
}

在DisclosureDetail.xib上放一个label把DisclosureDetail.xib的View及label 与DisclosureDetailViewController关联起来。

5.修改展示按钮控制器,建立按钮视图

这里需要建立第一个子控制来指向刚才构建的DisclosureDetailViewController

#import "SecondLevelViewController.h"@class DisclosureDetailViewController;
@interface DisclosureButtonViewController : SecondLevelViewController
@property (nonatomic,retain) NSArray *list;
@property (nonatomic,retain) DisclosureDetailViewController *childController;
@end

.m文件关键代码

//加载数据
- (void)viewDidLoad
{NSArray *array =[[NSArray alloc]initWithObjects:@"toy story",@"a bug's life",@"toy story1",@"jay", @"toy story2",@"hacker",@"toy story3",@"1326", @"toy story4",@"coding",   nil];self.list = array;[array release];[super viewDidLoad];// Do any additional setup after loading the view.
}
//释放销毁对象
-(void)dealloc
{[list release];[childController release];[super dealloc];
}
//返回行数
-(NSInteger) tableView :(UITableViewCell*) tableview numberOfRowsInSection:(NSInteger)section
{return [list count];
}
//绑定每行数据
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{static NSString *DisclocsutreButtonCellIdetifier = @"DisclosutreButtonCellIdetifier";UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:DisclocsutreButtonCellIdetifier];if(cell ==nil){cell =[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:DisclocsutreButtonCellIdetifier]autorelease];}NSUInteger row = [indexPath row];NSString *rowString = [list objectAtIndex:row];cell.textLabel.text = rowString;cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;[rowString release];return cell;
}
//处理不选中事件 这里要区别Deselect与Select
-(void) tableView:(UITableView*)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{UIAlertView *alert = [[UIAlertView alloc ]initWithTitle:@"Hey,Man" message:@"drill down,touch that instead" delegate:nil cancelButtonTitle:@"Won't happen again" otherButtonTitles:nil];[alert show];[alert release];}
//展示按钮方法
-(void) tableView:(UITableView*)tableViewaccessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{if(childController ==nil){childController = [[DisclosureDetailViewController alloc]initWithNibName:@"DisclosureDetail" bundle:nil];}childController.title = @"Disclosure Button Pressed";NSUInteger row = [indexPath row];NSString *selectMovie=[list objectAtIndex:row];NSString *detailMessage = [[NSString alloc]initWithFormat:@"You pressed the disclosure button for %@.",selectMovie];childController.message = detailMessage;childController.title = selectMovie;[detailMessage release];[self.navigationController pushViewController:childController animated:YES];//将详情视图推入控制器栈
}

6.回到FirstLevelViewController.m为Disclosure及其附属视图添加一个按钮控制器实例

关键代码:

- (void)viewDidLoad
{self.title =@"Frist Level 1326";NSMutableArray *array = [[NSMutableArray alloc]init];DisclosureButtonViewController *disclosureButtonController = [[DisclosureButtonViewController alloc] initWithStyle:UITableViewStylePlain];disclosureButtonController.title = @"Disclosure Buttons";disclosureButtonController.rowImage = [UIImage imageNamed:@"disclosureButtonControllerIcon.png"];[array addObject:disclosureButtonController];[disclosureButtonController release];self.controllers = array;[array release];[super viewDidLoad];}

当然,也要实现tableView的数据加载的三个方法及相关头文件引入。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{// Return the number of sections.return 1;
}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{// Return the number of rows in the section.return [self.controllers count];
}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{static NSString *CellIdentifier = @"FristLevelCell";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];if(cell ==nil){cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];}SecondLevelViewController *controller = self.controllers[indexPath.row];cell.textLabel.text = controller.title;cell.imageView.image = controller.rowImage;cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;// Configure the cell...return cell;
}

编译运行,效果如下:

添加第一个二级控制器之后的应用程序。

展示按钮视图

点击行视图

详细信息视图

通过4-6步骤的编码,就初步完成NavNice这个实例的1/6的工程,也看到多视图应用小小的成果。这看起来灰常的NICE~

7.第二个子控制器:校验表

依旧是建表视图,依旧是继承于SecondLevelViewController

#import "SecondLevelViewController.h"@interface CheckListViewController : SecondLevelViewController
@property (nonatomic,retain) NSArray *list;
@property (nonatomic,retain) NSIndexPath *lastIndexPath;@end

.m文件关键代码:

//数据初始化
- (void)viewDidLoad
{NSArray *array = [[NSArray alloc]initWithObjects:@"hi,man1326",@"4y",@"viewDidLoad",@"dealloc",@"fristblood",@"double kill",@"nice",@"...",@"okokok",nil];self.list = array;[array release];[super viewDidLoad];// Do any additional setup after loading the view.
}
//释放资源
-(void) dealloc
{[list release];[lastIndexPath release];[super dealloc];
}-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{return [list count];
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{static NSString *CheckMarkCellIdentifier = @"CheckMarkCellIdentifier";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CheckMarkCellIdentifier];if(cell==nil){cell =[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CheckMarkCellIdentifier]autorelease];}//从这个单元和当前选项提取行NSUInteger row = [indexPath row];NSUInteger oldRow = [lastIndexPath row];cell.textLabel.text = [list objectAtIndex:row];//将它分配给单元的标题cell.accessoryType = (row==oldRow&&lastIndexPath!=nil)?
UITableViewCellAccessoryCheckmark:UITableViewCellAccessoryNone;//如果选中则设图标 否则不显示任何东西return cell;
}-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{//获取选中行int newRow = [indexPath row];int oldRow = (lastIndexPath !=nil)?[lastIndexPath row]:-1;if(newRow !=oldRow){//修改图标UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];newCell.accessoryType = UITableViewCellAccessoryCheckmark;UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastIndexPath];oldCell.accessoryType = UITableViewCellAccessoryNone;       

self.lastIndexPath = indexPath;

} [tableView deselectRowAtIndexPath:indexPath animated:YES];//告诉表视图取消选中不凸显 }8.添加校验表到控制器实例

在FirstLevelViewController.m添加CheckListController的索引表视图

- (void)viewDidLoad
{self.title =@"Frist Level 1326";NSMutableArray *array = [[NSMutableArray alloc]init];//Disclosure ButtonDisclosureButtonViewController *disclosureButtonController = [[DisclosureButtonViewController alloc] initWithStyle:UITableViewStylePlain];disclosureButtonController.title = @"Disclosure Buttons";disclosureButtonController.rowImage = [UIImage imageNamed:@"disclosureButtonControllerIcon.png"];[array addObject:disclosureButtonController];[disclosureButtonController release];//ChecklistCheckListViewController *checkListController = [[CheckListViewController alloc]initWithStyle:UITableViewStylePlain];checkListController.title = @"check one";checkListController.rowImage = [UIImage imageNamed:@"checkmarkControllerIcon.png"];[array addObject:checkListController];[checkListController release];self.controllers = array;[array release];[super viewDidLoad];// Uncomment the following line to preserve selection between presentations.// self.clearsSelectionOnViewWillAppear = NO;// Uncomment the following line to display an Edit button in the navigation bar for this view controller.// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

编译运行,效果如下:

两行控制器,两行信息

点入check one页面

选中状态

9.第三个子控制器:行上的控件

依旧是建表视图,依旧是继承于SecondLevelViewController,这次命名为RowControlsController

RowControlsController.h文件代码

#import "SecondLevelViewController.h"@interface RowControlsController : SecondLevelViewController
@property(nonatomic,retain)NSArray *list;
-(IBAction)buttonTapped:(id)sender;
@end

RowControlsController.m文件核心代码

-(IBAction)buttonTapped:(id)sender
{UIButton *senderButton = (UIButton *)sender;UITableViewCell *buttonCell = (UITableViewCell*)[senderButton superview];NSUInteger buttonRow = [[self.tableView indexPathForCell:buttonCell] row];NSString *buttonTitle = [list objectAtIndex:buttonRow];UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"You tapped the button" message:[NSString stringWithFormat:@"You tapped the button for %@",buttonTitle] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles: nil];[alert show];[alert release];}- (void)viewDidLoad
{NSArray *array = [[NSArray alloc] initWithObjects:@"1326",@"1234",@"byebye",@"fouce",@"table",@"nice",@"good luck",@"48road",@"ganker", nil];self.list = array;[array release];[super viewDidLoad];// Do any additional setup after loading the view.
}-(void)dealloc
{[list release];[super dealloc];
}-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{return [list count];
}//数据源-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{static NSString * ControlRowIdentifier = @"ControlRowIdentifier";UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:ControlRowIdentifier];if(cell ==nil){cell =[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ControlRowIdentifier];UIImage *buttonUpImage=[UIImage imageNamed:@"button_up.png"];UIImage *buttonDownImage = [UIImage imageNamed:@"button_down.png"];UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];button.frame = CGRectMake(0.0, 0.0, buttonUpImage.size.width, buttonUpImage.size.height);[button setBackgroundImage:buttonUpImage forState:UIControlStateNormal];[button setBackgroundImage:buttonDownImage forState:UIControlStateHighlighted];[button setTitle:@"Tag" forState:UIControlStateNormal];[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];//注册事件cell.accessoryView= button;}NSUInteger row = [indexPath row];NSString *rowTitle =[list objectAtIndex:row];cell.textLabel.text= rowTitle;return cell;
}//选中行委托
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{NSUInteger row = [indexPath row];NSString *rowTitle =[list objectAtIndex:row];UIAlertView *alert =[[UIAlertView alloc] initWithTitle:@"you tapped the row" message:[NSString stringWithFormat:@"you tapped %@",rowTitle] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles: nil];[alert show];[alert release];[tableView deselectRowAtIndexPath:indexPath animated:YES];}

10. 在主程序中添加行控件控制器的实例

回到FristLevelViewController,修改ViewDidLoad方法,在中间初始化数据插入关键代码

    //Table rowRowControlsController *rowController = [[RowControlsController alloc]initWithStyle:UITableViewStylePlain];rowController.title = @"Row Controls";rowController.rowImage = [UIImage imageNamed:@"rowControlsIcon"];[array addObject:rowController];[rowController release];

OK,编译执行,效果如下:

初始化画面-多了行控件的子控制器

点进二级控制器后的界面:

选中行中按钮是弹出的消息窗口

选中行时弹出的提示-

11.第四个控制器-可移动的行

要建立可移动的行,可以使用表视图的setEditing:animated:方法打开编辑模式,这个方法带两个BOOLEAN类型的参数,第一个指示编辑模式是否被打开,第二个指示表是否进行动画转换~打开编辑模式后,大量的新委托方法就开始发挥作用,如询问某一行是否可以被编辑或移除,并告知用户是否移除或编辑特定行。

下面,依旧是建表视图,继承SecondLevelViewController,这次命名为MoveMeController。

.h

#import "SecondLevelViewController.h"@interface MoveMeController : SecondLevelViewController
@property (nonatomic,retain)NSMutableArray *list;
-(IBAction) toggleMove;
@end

.m关键代码

//操作方法
-(IBAction)toggleMove
{[self.tableView setEditing:!self.tableView.editing animated:YES];if(self.tableView.editing){[self.navigationItem.rightBarButtonItem setTitle:@"Done"];}else{[self.navigationItem.rightBarButtonItem setTitle:@"Move"];}
}- (void)viewDidLoad
{if(list==nil){NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"1623",@"y2ok",@"even",@"qazwsx",@"by",@"fly",@"boom",nil];self.list=array;[array release];}//初始化按钮UIBarButtonItem *moveBtn = [[UIBarButtonItem alloc]initWithTitle:@"Move" style:UIBarButtonItemStyleBordered target:self action:@selector(toggleMove)];self.navigationItem .rightBarButtonItem = moveBtn;[moveBtn release];[super viewDidLoad];// Do any additional setup after loading the view.
}-(void)dealloc
{[list release];[super dealloc];}-(NSInteger )tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{return [list count];
}-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{static NSString *MoveMeCellIdentifier = @"MoveMeCellIdentifier";UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:MoveMeCellIdentifier];if(cell==nil){cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MoveMeCellIdentifier]autorelease];cell.showsReorderControl = YES;//启用编辑模式需要设置为yes}NSUInteger row = [indexPath row];cell.textLabel.text = [list objectAtIndex:row];return cell;
}-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{return UITableViewCellEditingStyleNone;
}-(BOOL) tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{return YES;
}-(void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{NSUInteger fromRow = [sourceIndexPath row];NSUInteger toRow = [destinationIndexPath row];id object = [[list objectAtIndex:fromRow] retain];[list removeObjectAtIndex:fromRow];[list insertObject:object atIndex:toRow];[object release];
}

12. 在主程序中添加换行控件控制器的实例

    //move cellMoveMeController *moveMeConroller = [[MoveMeController alloc] initWithStyle:UITableViewStylePlain];moveMeConroller.title=@"Move Me";moveMeConroller.rowImage =[UIImage imageNamed:@"moveMeIcon.png"];[array addObject:moveMeConroller];[moveMeConroller release];

编译,运行效果:

一级页面:

二级页面:

点击Move

换行:

13.第五个子控制器-可删除的行

在启用表哥编辑模式后,可以对行进行移动调整,同样的可以可以对行进行删除。

依旧是建视图…

.h

#import "SecondLevelViewController.h"@interface DeleteMeController : SecondLevelViewController
@property (nonatomic,retain) NSMutableArray *list;
-(IBAction)toggleEdit:(id)sender;@end

.m关键代码

-(IBAction)toggleEdit:(id)sender
{[self.tableView setEditing:!self.tableView.editing animated:YES];if(self.tableView.editing){[self.navigationItem.rightBarButtonItem setTitle:@"Done"];}else{[self.navigationItem.rightBarButtonItem setTitle:@"Delete"];}
}- (void)viewDidLoad
{if(list==nil){NSString *path = [[NSBundle mainBundle]pathForResource:@"computers" ofType:@"plist"];NSMutableArray *array = [[NSMutableArray alloc]initWithContentsOfFile:path];self.list = array;[array release];}UIBarButtonItem *editBtn = [[UIBarButtonItem alloc ]initWithTitle:@"Delete" style:UIBarButtonItemStyleBordered target:self action:@selector(toggleEdit:)];//这里多了个: 是因为这个切换方法多了一个senderself.navigationItem.rightBarButtonItem = editBtn;[editBtn release];[super viewDidLoad];// Do any additional setup after loading the view.
}-(NSInteger ) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{return [list count ];
}-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{static NSString *DeleteMeCellIdentifier = @"DeleteMeCekkIdentifier";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DeleteMeCellIdentifier];if(cell ==nil){cell =[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:DeleteMeCellIdentifier] autorelease];}NSInteger row = [indexPath row];cell.textLabel.text = [self.list objectAtIndex:row];return cell;
}-(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{[self.list removeObjectAtIndex: [indexPath row]];[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];//最终指定动画 渐渐隐退}

14.依旧是在1级控制器中添加删除行的子控制器

打开FirstLevelViewController.h在 viewDidLoad中添加代码

    //Delete MeDeleteMeController *deleteMeController = [[DeleteMeController alloc]initWithStyle:UITableViewStylePlain];deleteMeController.title = @"Delete Me";deleteMeController.rowImage = [UIImage imageNamed:@"deleteMeIcon.png"];[array addObject:deleteMeController];[deleteMeController release];self.controllers = array;

编译执行,效果如下:

主页面

子控制器页面

可编辑状态页面

按左边按钮之后出现的删除按钮

15.第六个子控制器-可编辑的详情页实现

15.1.由于详情页的字内容来自于一个归档好的文件,这里需要先建一个实现<NSCoding>的协议来操作这个文件。

President源码如下

#import "SecondLevelViewController.h"
#define kPresidentNumberKey @"President"
#define kPresidentNameKey @"Name"
#define kPresidentToKey @"ToYear"
#define kPresidentFromKey @"FromYear"
#define kPresidentPartyKey @"Party"
@interface President : NSObject
{int number;NSString *name;NSString *fromYear;NSString *toYear;NSString *party;}
@property int number ;
@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSString *fromYear;
@property (nonatomic,copy) NSString *toYear;
@property (nonatomic,copy) NSString *party;@end
#import "President.h"@interface President ()@end@implementation President@synthesize number;
@synthesize name;
@synthesize fromYear;
@synthesize toYear;
@synthesize party;-(void) dealloc
{[name release];[fromYear release];[toYear release];[party release];[super dealloc];
}//把对象编码为归档文件
-(void)encodeWithCoder:(NSCoder *)coder
{[coder encodeInt:self.number forKey:kPresidentNumberKey];[coder encodeObject:self.name forKey:kPresidentNameKey];[coder encodeObject:self.fromYear forKey:kPresidentFromKey];[coder encodeObject:self.toYear forKey:kPresidentToKey];[coder encodeObject:self.party forKey:kPresidentPartyKey];
}//从归档文件创建出对象
-(id)initWithCoder:(NSCoder *)coder
{if(self=[super init]){number =[coder decodeIntForKey:kPresidentNumberKey];name = [[coder decodeObjectForKey:kPresidentNumberKey] retain];fromYear = [[coder decodeObjectForKey:kPresidentFromKey] retain];toYear = [[coder decodeObjectForKey:kPresidentToKey] retain];party = [[coder decodeObjectForKey:kPresidentPartyKey] retain];}return self;
}
@end

15.2.接下来创建视图列表

PresidentViewController 源码如下

.h关键代码
#import "SecondLevelViewController.h"@interface PresidentViewController : SecondLevelViewController
{NSMutableArray *list;
}@property (nonatomic,retain) NSMutableArray *list;
@end
.m关键代码
//初始化
- (void)viewDidLoad {NSString *path = [[NSBundle mainBundle] pathForResource:@"Presidents"ofType:@"plist"];NSData *data; NSKeyedUnarchiver *unarchiver;data = [[NSData alloc] initWithContentsOfFile:path];unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; NSMutableArray *array = [unarchiver decodeObjectForKey:@"Presidents"];self.list = array;[unarchiver finishDecoding];[unarchiver release];[data release];[super viewDidLoad]; }//父视图会重新加载数据
- (void)viewWillAppear:(BOOL)animated { [self.tableView reloadData];[super viewWillAppear:animated];
}//销毁
- (void)dealloc {[list release];[super dealloc];
}
#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section { return [list count];
}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath {static NSString *PresidentListCellIdentifier = @"PresidentListCellIdentifier";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PresidentListCellIdentifier];if (cell == nil) {cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PresidentListCellIdentifier] autorelease];}NSUInteger row = [indexPath row];President *thePres = [self.list objectAtIndex:row]; cell.textLabel.text = thePres.name;cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ - %@",thePres.fromYear, thePres.toYear];return cell;
}
#pragma mark -
#pragma mark Table Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger row = [indexPath row];President *prez = [self.list objectAtIndex:row];PresidentDetailController *childController =[[PresidentDetailController alloc] initWithStyle:UITableViewStyleGrouped];childController.title = prez.name; childController.president = prez;[self.navigationController pushViewController:childController animated:YES];[childController release];}

15.3.视图详情页的视图

PresidentDetailController

.h文件详情 这里实现了一个TextField的委托它和tableView的数据源委托原理差不多

#import <UIKit/UIKit.h>
@class President;#define kNumberOfEditableRows 4
#define kNameRowIndex 0
#define kFromYearRowIndex 1
#define kToYearRowIndex 2
#define kPartyIndex 3
#define kLabelTag 4096@interface PresidentDetailController : UITableViewController<UITextFieldDelegate>
{President *president;NSArray *fieldLabels; NSMutableDictionary *tempValues; UITextField *textFieldBeingEdited;
}
@property (nonatomic, retain) President *president;
@property (nonatomic, retain) NSArray *fieldLabels;
@property (nonatomic, retain) NSMutableDictionary *tempValues;
@property (nonatomic, retain) UITextField *textFieldBeingEdited;
- (IBAction)cancel:(id)sender;
- (IBAction)save:(id)sender;
- (IBAction)textFieldDone:(id)sender;
@end

.m文件关键代码

- (IBAction)cancel:(id)sender {[self.navigationController popViewControllerAnimated:YES];
}
- (IBAction)save:(id)sender {if (textFieldBeingEdited != nil) { NSNumber *tagAsNum= [[NSNumber alloc]initWithInt:textFieldBeingEdited.tag]; [tempValues setObject:textFieldBeingEdited.text forKey: tagAsNum];[tagAsNum release]; }for (NSNumber *key in [tempValues allKeys]) { switch ([key intValue]) {case kNameRowIndex:president.name = [tempValues objectForKey:key]; break;case kFromYearRowIndex:president.fromYear = [tempValues objectForKey:key]; break;case kToYearRowIndex:president.toYear = [tempValues objectForKey:key];break;case kPartyIndex:president.party = [tempValues objectForKey:key]; default:break; }}[self.navigationController popViewControllerAnimated:YES];NSArray *allControllers = self.navigationController.viewControllers; UITableViewController *parent = [allControllers lastObject]; [parent.tableView reloadData];
}
- (IBAction)textFieldDone:(id)sender { [sender resignFirstResponder];
}
#pragma mark -
- (void)viewDidLoad {NSArray *array = [[NSArray alloc] initWithObjects:@"Name:", @"From:", @"To:", @"Party:", nil];self.fieldLabels = array; [array release];UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel"style:UIBarButtonItemStylePlain target:self action:@selector(cancel:)];self.navigationItem.leftBarButtonItem = cancelButton; [cancelButton release];UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithTitle:@"Save"style:UIBarButtonItemStyleDone target:self action:@selector(save:)];self.navigationItem.rightBarButtonItem = saveButton; [saveButton release];NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; self.tempValues = dict;[dict release];[super viewDidLoad];
}
- (void)dealloc {[president release]; [fieldLabels release]; [tempValues release]; [textFieldBeingEdited release]; [super dealloc];
}#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section { return kNumberOfEditableRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {static NSString *PresidentCellIdentifier = @"PresidentCellIdentifier";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: PresidentCellIdentifier];if (cell == nil) {cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:PresidentCellIdentifier] autorelease]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 75, 25)]; label.textAlignment = UITextAlignmentRight;label.tag = kLabelTag;label.font = [UIFont boldSystemFontOfSize:14]; [cell.contentView addSubview:label];[label release];UITextField *textField = [[UITextField alloc] initWithFrame: CGRectMake(90, 12, 200, 25)];textField.clearsOnBeginEditing = NO; [textField setDelegate:self]; textField.returnKeyType = UIReturnKeyDone; [textField addTarget:self action:@selector(textFieldDone:) forControlEvents:UIControlEventEditingDidEndOnExit];[cell.contentView addSubview:textField];}NSUInteger row = [indexPath row];UILabel *label = (UILabel *)[cell viewWithTag:kLabelTag]; UITextField *textField = nil;for (UIView *oneView in cell.contentView.subviews) {if ([oneView isMemberOfClass:[UITextField class]]) textField = (UITextField *)oneView;}label.text = [fieldLabels objectAtIndex:row];NSNumber *rowAsNum = [[NSNumber alloc] initWithInt:row];switch (row) {case kNameRowIndex:if ([[tempValues allKeys] containsObject:rowAsNum])textField.text = [tempValues objectForKey:rowAsNum];elsetextField.text = president.name;break;case kFromYearRowIndex:if ([[tempValues allKeys] containsObject:rowAsNum])textField.text = [tempValues objectForKey:rowAsNum];elsetextField.text = president.fromYear; break;case kToYearRowIndex:if ([[tempValues allKeys] containsObject:rowAsNum])textField.text = [tempValues objectForKey:rowAsNum];elsetextField.text = president.toYear; break;case kPartyIndex:if ([[tempValues allKeys] containsObject:rowAsNum])textField.text = [tempValues objectForKey:rowAsNum];elsetextField.text = president.party; default:break; }if (textFieldBeingEdited == textField) { textFieldBeingEdited = nil;}textField.tag = row; [rowAsNum release]; return cell;
}
#pragma mark -
#pragma mark Table Delegate Methods
- (NSIndexPath *)tableView:(UITableView *)tableViewwillSelectRowAtIndexPath:(NSIndexPath *)indexPath { return nil;
}
#pragma mark Text Field Delegate Methods
- (void)textFieldDidBeginEditing:(UITextField *)textField {self.textFieldBeingEdited = textField; }
- (void)textFieldDidEndEditing:(UITextField *)textField {NSNumber *tagAsNum = [[NSNumber alloc] initWithInt:textField.tag]; [tempValues setObject:textField.text forKey:tagAsNum];[tagAsNum release];
}

15.4.把视图列表添加到第二级的控制器中

在FristLevel下添加代码

    // President View/EditPresidentViewController *presidentViewController =[[PresidentViewController alloc]initWithStyle:UITableViewStylePlain]; presidentViewController.title = @"Detail Edit"; presidentViewController.rowImage = [UIImage imageNamed:@"detailEditIcon.png"];[array addObject:presidentViewController];[presidentViewController release];

那么这样就把最后一个子控制器也添加进一级控制器了。

好啦,编码任务完成~~~

------------------------源码-----------------------

在这个Nav的练习中学到很多关于导航控制器的东西,多视图应用离不开这个,所以回头还得多多研究下~

文章的最后是一个福利时间,对于表视图及导航的学习主要通过一本开发书籍去系统学习的,

这是在网上找到的英文PDF版,分享给大家,大家也可以参考书中的例子来学习喔~

iPhone4与iPad开发基础教程 英文原版PDF及源码

IOS开发-表视图LV3导航控制器相关推荐

  1. iOS开发UINavigation系列四——导航控制器UINavigationController

    iOS开发UINavigation系列四--导航控制器UINavigationController 一.引言 在前面的博客中,我么你介绍了UINavigationBar,UINavigationIte ...

  2. IOS开发之视图和视图控制器

    视图(View), 视图控制器(ViewController)是IOS开发UI部分比较重要的东西.在学习视图这一块的东西的时候,感觉和Java Swing中的Panel差不多.在UIKit框架中都有一 ...

  3. ios 地图黑屏_ios – 导航控制器显示黑屏

    我正在学习iOS开发并遇到导航控制器的一些问题. 我创建了一个SingleView应用程序,然后使用"嵌入导航控制器"来获得导航控件. 我遇到的问题是,在应用程序成功构建之后,只有 ...

  4. ios百度导航SDK,iOS开发之百度地图导航

    若遇到疑难问题可以去   ios导航SDK 论坛问题  查看和反馈:http://bbs.lbsyun.baidu.com/forum.php?mod=forumdisplay&fid=37 ...

  5. iOS开发 - 一个天真的搜索控制器的独白

    文/Azen(简书作者) 原文链接:http://www.jianshu.com/p/6d5327111511 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". 正文 ...

  6. iOS开发中视图相关的小笔记:push、modal、popover、replace、custom

    在storyboard中,segue有几种不同的类型,在iphone和ipad的开发中,segue的类型是不同的. 在iphone中,segue有:push,modal,和custom三种不同的类型, ...

  7. iOS 开发之 - iOS6适配 - 导航栏按钮透明方法

    首先上张图: 1:ios6导航栏默认按钮 rightBarButtonItem   是不是很丑的赶脚? 现在通过以下方法来改变以下:code: UIButton *rightButton = [UIB ...

  8. iOS开发之--改变系统导航的颜色,字体,还有返回样式的自定义

    在写项目的工程中,我们可能会遇到各种各样的项目,写的方法也是各有不同,不喜欢自定义的小伙伴也很多, 下面我就记录下系统导航和barbuttonitem的修改系统空间的方法: 1,添加rightbarb ...

  9. iOS开发笔记1:[转]导航栏里的Back按钮显示不出来

    最近项目中遇到一个问题,push过去的ViewController的Nav上面没有返回按钮,遂搜索资料,找到了以下文档.经测试i,问题解决. 原文地址:http://www.cnblogs.com/s ...

最新文章

  1. 重磅!MaxCompute助力阿里开源自研语音识别模型DFSMN,准确率高达96.04%
  2. SpringMVC如何实现restful接口
  3. php 如何发送json数据格式,Php如何使用curl发送json格式数据实例
  4. React 教程:快速上手指南
  5. 微信小程序,时间戳和日期格式互相转化
  6. 理解离散傅立叶变换(一. 傅立叶变换的由来)
  7. 在MFC中显示Jpg格式图片的简单实现方法
  8. 前端05.js入门之BOM对象与DOM对象。
  9. 马蹄疾 | 聊聊你可能并没有完全掌握的 Flex 布局:从概念入手,丝丝入扣
  10. jwt如何加盐_手把手教你使用JWT实现单点登录
  11. [黑苹果]G480 黑苹果之路
  12. 学习搭建谷粒商城微服务框架(Docker配置)-01
  13. maven 为html赋版本号,maven-replacer-plugin 静态资源版本号解决方案(css/js等)
  14. 简单小方法教你如何快速提高记忆力
  15. 【Microsoft Azure 的1024种玩法】十五.通过Web浏览器对Auzre VM 服务器运维管理
  16. windows启动tomcat乱码问题
  17. SpringCloud-2-Eureka注册中心
  18. 《HelloGitHub》第 41 期
  19. 运维经理应具备的能力
  20. 全球最具影响力的大数据企业排行榜

热门文章

  1. unix--Tripwire 应用
  2. [源码]C# to SQL 的翻译器.net 1.1版
  3. 华为机试HJ21:简单密码
  4. move语句java_java 程序里 有几个地方不明白 1、angle 方法 前两个if 语句 2、movex 、movey 方法作用 3、rotate 方法...
  5. dataframe数组做元素_大数据技术之使用 DataFrame 读取复杂 JSON 中的嵌套数组
  6. 昆仑通态如何连接sqlserver数据库_三菱FX5U 与昆仑通态触摸屏的连接操作步骤
  7. k1658停运到什么时候_2021年春运就要开始啦!快来看看各大快递的停运时间吧
  8. 听说你不会用datetime处理时间?
  9. 资深和新手的100大 Selenium面试问答
  10. 软件性能测试——负载测试的最佳实践