表视图是显示表数据的视图对象,它是UITableView类的一个实例,表中的每个可见行都由UITableviewCell类实现。
表视图并不负责存储表中的数据,他们只存储足够绘制当前可见行的数据。
表视图从遵循UITableviewDelegate协议的对象获取配置数据,从遵循UITableviewDataSource协议的对象获得行数据。
第一个例子:SimpleTable
1、新建Single View Application项目
2、打开ViewController.xib,拖出一个TableView到界面上,在Connection里,将dataSource和delegate连接到File's Owner上
3、修改控制器
ViewController.h
@interface ViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
NSArray *listData;
}
@property (nonatomic,retain) NSArray *listData;
@end
ViewController.m
@implementation ViewController
@synthesize listData;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
NSArray *array = [[NSArray alloc] initWithObjects:@"Sleep",@"Sneey",
@"Bashful",@"Happy",nil];
self.listData = array;
[array release];
[super viewDidLoad];
}
- (void)dealloc {
[listData release];
[super dealloc];
}
- (NSInteger)tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger)section
{
return [self.listData count];
}
//当表视图需要绘制其中一行时,会调用次方法
-(UITableViewCell *) tableView:(UITableViewCell *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.text = [listData objectAtIndex:row];
return cell;
}
4、运行
添加一个图像
1、添加icon图像资源到项目中
2、修改ViewController.m
//当表视图需要绘制其中一行时,会调用次方法
-(UITableViewCell *) tableView:(UITableViewCell *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.text = [listData objectAtIndex:row];
cell.font = [UIFont boldSystemFontOfSize:40];
UIImage *image = [UIImage imageNamed:@"plane.jpg"];
cell.image = image;
return cell;
}
设置图像缩进
//设置每一行的缩进
-(NSInteger)tableView:(UITableView *) tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
return row;
}
设置第一列不能点钟
-(NSIndexPath *)tableView:(UITableView *) tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
if (row == 0) {
return nil;
}
return indexPath;
}
点击每一列,弹出一个对话框
-(void)tableView:(UITableView *) tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSString *rowValue = [listData objectAtIndex:row];
NSString *message = [[NSString alloc] initWithFormat:@"You selected %@",rowValue];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Row Selected" message:message delegate:nil cancelButtonTitle:@"Yes,I Did" otherButtonTitles:nil, nil];
[alert show];
[message release];
[alert release];
}
字体变大
//当表视图需要绘制其中一行时,会调用次方法
-(UITableViewCell *) tableView:(UITableViewCell *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.text = [listData objectAtIndex:row];
cell.font = [UIFont boldSystemFontOfSize:40];
UIImage *image = [UIImage imageNamed:@"plane.jpg"];
cell.image = image;
return cell;
}
每一列高度加大-(CGFloat)tableView:(UITableView *) tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}
第二个例子:自定义表视图单元
可以采用两种方法,一是向UITableViewCell添加子视图,二是,创建一个UITableViewCell的子类
1、参考例子一,新建项目,打开xib文件,视图拖出一个TableView视图,dataSource dataDelegate连接到File's Owner上
2、修改控制器
#import <UIKit/UIKit.h>
#define kNameValueTag 1 //定义了两个常量,将使用这两个常量为将要添加到表视图中的子视图分配标记
#define kColorValueTag 2
@interface ViewController : UIViewController<UITabBarDelegate,UITabBarDelegate>
{
NSArray *computers;
}
@property (nonatomic,retain) NSArray *computers;
@end
@implementation ViewController @synthesize computers; - (void)viewDidLoad { NSDictionary *row1 = [[NSDictionary alloc] initWithObjectsAndKeys:@"MacBook",@"Name",@"White",@"Color", nil]; NSDictionary *row2 = [[NSDictionary alloc] initWithObjectsAndKeys:@"MacBook Pro",@"Name",@"Silver",@"Color", nil]; NSDictionary *row3 = [[NSDictionary alloc] initWithObjectsAndKeys:@"iMac",@"Name",@"White",@"Color", nil]; NSArray *array = [[NSArray alloc] initWithObjects:row1,row2,row3, nil]; self.computers = array; [super viewDidLoad]; [row1 release]; [row2 release]; [row3 release]; [array release]; } - (void)dealloc { [computers release]; [super dealloc]; } -(NSInteger)tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger)section { return [self.computers count]; } -(UITableViewCell *)tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellTableIdentfier = @"CellTableIdentfier"; //创建了一个新的单元 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellTableIdentfier]; //如果表提供了出列的表视图单元,则要求表将该单元推出队列 if (cell == nil) { CGRect cellFrame = CGRectMake(0, 0, 300, 65); cell = [[[UITableViewCell alloc] initWithFrame:cellFrame reuseIdentifier:CellTableIdentfier] autorelease]; CGRect nameLabelRect = CGRectMake(0, 5, 70, 15); UILabel *nameLabel = [[UILabel alloc] initWithFrame:nameLabelRect]; nameLabel.textAlignment = UITextAlignmentRight; nameLabel.text = @"Name:"; nameLabel.font = [UIFont boldSystemFontOfSize:12]; [cell.contentView addSubview:nameLabel]; [nameLabel release]; CGRect colorLabelRect = CGRectMake(0, 25, 70, 15); UILabel *colorLabel = [[UILabel alloc] initWithFrame:colorLabelRect]; colorLabel.textAlignment = UITextAlignmentRight; colorLabel.text = @"Color:"; colorLabel.font = [UIFont boldSystemFontOfSize:12]; [cell.contentView addSubview:colorLabel]; [colorLabel release]; CGRect nameValueRect = CGRectMake(80, 5, 200, 15);; UILabel *nameValue = [[UILabel alloc] initWithFrame:nameValueRect]; nameValue.tag = kNameValueTag; [cell.contentView addSubview:nameValue]; //表视图单元已经有了一个名为contentView的UIView子视图,用于对它的所有子视图进行分组。不用把标签作为子视图直接添加到表视图单元,而是添加到contentView [nameValue release]; CGRect colorValueRect = CGRectMake(80, 25, 200, 15);; UILabel *colorValue = [[UILabel alloc] initWithFrame:colorValueRect]; colorValue.tag = kColorValueTag; [cell.contentView addSubview:colorValue]; [colorValue release]; } NSUInteger row = [indexPath row]; NSDictionary *rowData = [self.computers objectAtIndex:row];
UILabel *name = (UILabel *)[cell.contentView viewWithTag:kNameValueTag]; name.text = [rowData objectForKey:@"Name"]; UILabel *color = (UILabel *)[cell.contentView viewWithTag:kColorValueTag]; color.text = [rowData objectForKey:@"Color"]; return cell;}// 检索到标签以后,只需将标签文本设置为从表示此行的字典里获取的一个值
第三个例子:使用UITableViewCell自定义子类
1、在第二个例子的基础上做修改,新建UIViewController subclass 名为CustomCell,继承自UITableViewCell,注意勾选 With XIB ...

2、修改控制器
@interface CustomCell : UITableViewCell{
IBOutlet UILabel *nameLabel;
IBOutlet UILabel *colorLabel;
}
@property (nonatomic,retain) UILabel *nameLabel;
@property (nonatomic,retain) UILabel *colorLabel;
@implementation CustomCell
@synthesize nameLabel;
@synthesize colorLabel;
3、打开CustomView.xib,拖一个Table View Cell到dock上(不是界面上),把dock的view删掉
选中Table View Cell 将class改为 CustomCell ,高度改为65,属性面板:Identifier改为CustomCellIdentifier
拖4个label到界面上,排列好

按Control 把Custom Cell图标拖到Label图标上,在弹出的框,选择nameLabel输出口,重复实现colorLabel

4、修改控制器文件
替换掉原来的
cellForRowAtIndexPath方法
- (UITableViewCell *) tableView:(UITableViewCell *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CustomCellIdentifier = @"CustomCellIdentifier";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CustomCellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSInteger row = [indexPath row];
NSDictionary *rowData = [self.computers objectAtIndex:row];
cell.colorLabel.text = [rowData objectForKey:@"Color"];
cell.nameLabel.text = [rowData objectForKey:@"Name"];
return cell;
}
-(CGFloat)tableView:(UITableView *) tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return kTableViewRowHeight;
}
5、在头文件中,修改如下

6、运行,看效果

第四个例子:分组分区索引分区
1、参照例一,新建项目,打开xib文件,视图拖出一个TableView视图,dataSource dataDelegate连接到File's Owner上
2、打开ViewController.xib,选中表视图,把表视图的Style改为Grouped
3、导入数据文件storednames.plist
4、修改控制器
@interface ViewController : UIViewController<UITabBarDelegate,UITabBarDelegate>
{
NSDictionary *names;
NSArray *keys;
}
@property (nonatomic,retain) NSDictionary *names;
@property (nonatomic,retain) NSArray *keys;
@implementation ViewController
@synthesize names;
@synthesize keys;
- (void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:@"sortednames"
ofType:@"plist"];
NSDictionary *dict = [[NSDictionary alloc]
initWithContentsOfFile:path];
self.names = dict;
[dict release];
NSArray *array = [[names allKeys] sortedArrayUsingSelector:
@selector(compare:)];
self.keys = array;
}
- (void)viewDidUnload {
self.names = nil;
self.keys = nil;
}
- (void)dealloc {
[names release];
[keys release];
[super dealloc];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [keys count];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
return [nameSection count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
SectionsTableIdentifier ];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier: SectionsTableIdentifier ] autorelease];
}
cell.text = [nameSection objectAtIndex:row];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section
{
NSString *key = [keys objectAtIndex:section];
return key;
}
//添加如下方法,可以显示索引表
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return keys;
}

第四个例子:实现搜索栏
我们拥有一个包含多个数组的字典,其中字母表的每个字母都占有一个数组,该字典是不可改变的,这就意为着不能从字典添加或删除,它包含的数组也是如此。当用户取消搜索或者更改搜索项时,还必须能够返回到源数据集。
我们能做的就是创建两个新的字典:一个包含完整数据集的不可变的字典、一个可以从中删除行的可变的字典副本。委托和数据源将从可变字典进行读取,当搜索标准更改或者取消搜索时,可以从不可改变的字典刷新可变字典。

1、新建Empty File 文件名:NSDdictionary-MutableDeepCopy.m NSDdictionary-MutableDeepCopy.h
@interface NSDictionary (MutableDeepCopy)
-(NSMutableDictionary *) mutableDeepCopy;
@end
@implementation NSDictionary (MutableDeepCopy)
- (NSMutableDictionary *) mutableDeepCopy
{
NSMutableDictionary *ret = [NSMutableDictionary dictionaryWithCapacity:[self count]];
NSArray *keys = [self allKeys];
for (id key in keys) {
id oneValue = [self valueForKey:key];
id oneCopy = nil;
if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])
oneCopy = [oneValue mutableDeepCopy];
else if ([oneValue respondsToSelector:@selector(mutableCopy)])
oneCopy = [oneValue mutableCopy];
else
oneCopy = [oneValue copy];
[ret setValue:oneCopy forKey:key];
}
return ret;
}
@end
@interface ViewController : UIViewController<UITabBarDelegate,UITabBarDelegate,UISearchBarDelegate>
{
//NSDictionary *names;
//NSArray *keys;
IBOutlet UITableView *table;
IBOutlet UISearchBar *search;
NSDictionary *allNames;
NSMutableDictionary *names;
NSMutableArray *keys;
}
@property (nonatomic,retain) UITableView *table;
@property (nonatomic,retain) UISearchBar *search;
@property (nonatomic,retain) NSDictionary *allNames;
@property (nonatomic,retain) NSMutableDictionary *names;
@property (nonatomic,retain) NSMutableArray *keys;
-(void) resetSearch;
-(void) handleSearchFroTerm:(NSString *) searchTerm;
@end
@implementation ViewController
@synthesize names;
@synthesize keys;
@synthesize table;
@synthesize search;
@synthesize allNames;
-(void)resetSearch
{
self.names = [self.allNames mutableDeepCopy];
NSMutableArray *keyArray = [[NSMutableArray alloc] init];
[keyArray addObjectsFromArray:[[self.allNames allKeys] sortedArrayUsingSelector:@selector(compare:)]];
self.keys = keyArray;
[keyArray release];
}
- (void) handleSearchFroTerm:(NSString *)searchTerm
{
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc]init];
[self resetSearch];
for (NSString *key in self.keys){
NSMutableArray *array = [names valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in array){
if ([name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location == NSNotFound) {
[toRemove addObject:name];
}
if ([array count] == [toRemove count]) {
[sectionsToRemove addObject:toRemove];
[toRemove release];
}
}
[self.keys removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[table reloadData];
}
}
- (void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:@"sortednames"
ofType:@"plist"];
NSDictionary *dict = [[NSDictionary alloc]
initWithContentsOfFile:path];
//self.names = dict;
self.allNames =dict;
[dict release];
//NSArray *array = [[names allKeys] sortedArrayUsingSelector: @selector(compare:)];
//self.keys = array;
[self resetSearch];
search.autocapitalizationType = UITextAutocapitalizationTypeNone;
search.autocorrectionType =UITextAutocorrectionTypeNo;
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.names = nil;
self.keys = nil;
}
- (void)dealloc {
[table release];
[search release];
[allNames release];
[names release];
[keys release];
[super dealloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//return [keys count];
return ([keys count]>0)?[keys count]:1;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
if ([keys count] == 0) {
return 0;
}
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
return [nameSection count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
static NSString *sectionsTableIdentifier = @"sectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
sectionsTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:sectionsTableIdentifier] autorelease];
}
cell.text = [nameSection objectAtIndex:row];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section
{
if ([keys count] == 0) {
return @"";
}
NSString *key = [keys objectAtIndex:section];
return key;
}
- (NSArray *) sectionIndexTitleForTableView:(UITableView *) tableview
{
return keys;
}
- (NSIndexPath *) tableView:(UITableView *) tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[search resignFirstResponder];
return indexPath;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
NSString *searchTerm = [searchBar text];
[self handleSearchFroTerm:searchTerm];
}
-(void)searchBar:(UISearchBar *) searchBar textDidChange:(NSString *)searchText
{
if ([searchText length] == 0) {
[self resetSearch];
[table reloadData];
return;
}
[self handleSearchFroTerm:searchText];
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
searchBar.text = @"";
[self resetSearch];
[table reloadData];
[searchBar resignFirstResponder];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return keys;
}