【update 2013-03-13 添加了分组的表格的示例】

今天开始学使用表格。iOS的表格是UITableView实现的,一个table包含多行,但每行只有一列。

首先我们新建一个Single View或者Empty的项目。如果是Single View的项目,就无视interface builder和生成的MainStoryboard.storyboard文件吧。

在ViewController.h中,我们需要实现两个UITableView有关的protocol,并且添加两个变量:表格的数据listData,以及UITableView的实例。修改完后的文件如下:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
@property(strong, nonatomic) NSArray *listData;
@property(strong, nonatomic) UITableView *table;
@end

这个ViewController实现了UITableViewDelegate和UITableViewDataSource两个protocol。

表格的数据是放在一个NSArray中,当然这并不是强制的,只要在UITableViewDataSource的接口实现中,保证加载行的时候能取到数据就可以,下面会再提到。

接下来就是实现ViewController.m,先贴出完整的代码,然后逐步分析:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize listData, table;

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    self.listData = [[NSArray alloc] initWithObjects:@"aaaa",@"bbbb",@"cccc",@"dddd",
        @"eeee", @"ffffffff", @"gggg", @"hhhhhhhhhhhh", @"iiiiiii", @"jjjjjj", @"kkkkk",
    @"lllll", @"mmmmm", @"nnnnnn", @"oooooooo", @"pppppp",nil];
    self.table = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStylePlain];
    self.table.scrollEnabled = YES;
    self.table.dataSource = self;
    self.table.delegate = self;
    
    [self.view addSubview:table];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void) viewDidUnload
{
    [super viewDidUnload];
    listData=nil;
}


-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.listData count];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *key = @"key";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:key];
    if(cell == nil){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:key];
    }
    NSUInteger rowIndex = [indexPath row];
    cell.textLabel.text = [listData objectAtIndex:rowIndex];
    
    return cell;
}

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSUInteger rowIndex = [indexPath row];
    NSString *rowValue = [listData objectAtIndex:rowIndex];
    NSString *msg = [[NSString alloc] initWithFormat:@"You selected %@", rowValue];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Row selected" message:msg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
}
@end

在ViewDidLoad方法中,做了以下事情:

1. 初始化listData,即表格的数据

2. 初始化table实例,设置表格可滚动。

3. table.dataSource的值是id<UITableViewDataSource>类型的,即实现这个protocol的类。self.table.dataSource=self; 则告诉它指定了ViewController这个类实现了这个protocol。同样,table.delegate=self 告诉它ViewController类也实现了UITableViewDelegate这个protocol。

4. 将table添加到subviews。

接下来是几个protocol的方法实现:

tableView:numberOfRowsInSection方法返回表格的数据行数。

tableView:cellForRowAtIndexPath方法在创建每一个table cell(即每一行数据)的时候调用。一个table会包含多个table cell,但是一页中显示的table cell数一般是确定的,因此在显示的时候,我们尽量复用原来的视图,而不重新创建,以节省开销和提高效率。这个方法就对table cell做了缓存,它会先根据key来调用:tableViewdequeueReusableCellWithIdentifier:key 方法来确定这个table cell是否之前已经被创建(注意这里的key是任意的字符串),只有未被缓存的情况下,才会重新生成。然后获取当前所在行,并用listData对应的数据来填充。

cell除了textLabel之外,还有detailTextLabel(可以在创建cell时指定style=UITableViewCellStyleSubtitle,并给detailTextLabel.text指定值试试看~),还可以设置cell.imageView.image和cell.imageView.highlightedImage来分别指定cell的默认图标及选中时的图标。

tableView:didSelectRowAtIndexPath方法在table cell被选中时调用。这里可以获取选中的行及值,然后做些其他的逻辑。

最后Command+r执行一下就可以啦~~


上面演示的是最简单的表格,接下来我们尝试一下分组的表格,它的样式看起来是像这样的:

ios 表单 ios 表格_ios 表单


仍然在上面的例子上修改,因为是分组的,所以会有多个section,每个section都会有一系列的数据,为了简单,我们就有两个数组来存储数据:

NSArray *sections:存储分组数据

NSArray *sectionData:存储每个分组的数据(每个元素的值也是一个NSArray)

这样我们在ViewController.h中修改定义如下:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
@property(strong, nonatomic) UITableView *table;
@property(strong, nonatomic) NSArray *sections;
@property(strong, nonatomic) NSArray *sectionData;
-(void) loadData;
@en

loadData是一个另外添加的私有方法,在这个方法里我们对这些表格的数据做初始化。它的代码很简单:

@synthesize table, sections, sectionData;

- (void) loadData
{
    NSArray *sec1Data = [[NSArray alloc] initWithObjects:@"aaaaa",@"bbbb",@"ccccc", nil];
    NSArray *sec2Data = [[NSArray alloc] initWithObjects:@"dddd", @"eeeeee", @"ffffff",nil];
    NSArray *sec3Data = [[NSArray alloc] initWithObjects:@"ggggg", @"hhhh", @"iiii", @"jjjjj" ,nil];
    NSArray *sec4Data = [[NSArray alloc] initWithObjects:@"kkkkk", @"llll", @"mmmm", @"nnnn" ,nil];
    
    self.sections = [[NSArray alloc] initWithObjects:@"Sec1", @"Sec2", @"Sec3", @"Sec4", nil];
    self.sectionData = [[NSArray alloc] initWithObjects:sec1Data, sec2Data, sec3Data, sec4Data, nil];
}

接下来修改viewDidLoad方法:

- (void)viewDidLoad
{
    [super viewDidLoad];
   
    [self loadData];
    self.table = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStyleGrouped];
    self.table.scrollEnabled = YES;
    self.table.dataSource = self;
    self.table.delegate = self;
    
    [self.view addSubview:table];
}

注意这里的style变成了UITableViewStyleGrouped。

除了原来的numberOfRowsInSection修改了:

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [(NSArray*)[sectionData objectAtIndex:section] count];
}

因为有多个section,我们还需要实现numberOfSectionsInTableView方法:

-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
    return [sections count];
}

以及titleForHeaderInSection方法,用来展示每个section的header标题:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return [sections objectAtIndex:section];
}

再修改原来的两个方法:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *key = @"key";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:key];
    if(cell == nil){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:key];
    }
    NSUInteger sectionIndex = [indexPath section];
    NSUInteger rowIndex = [indexPath row];
    cell.textLabel.text = [(NSArray*)[sectionData objectAtIndex:sectionIndex] objectAtIndex:rowIndex];
    
    return cell;
}

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSUInteger sectionIndex = [indexPath section];
    NSUInteger rowIndex = [indexPath row];
    NSString *rowValue = [(NSArray*)[sectionData objectAtIndex:sectionIndex] objectAtIndex:rowIndex];
    NSString *msg = [[NSString alloc] initWithFormat:@"You selected %@", rowValue];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Row selected" message:msg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
}

然后就可以啦~