#import <UIKit/UIKit.h>
@interface TWFXViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
- (IBAction)btnClick:(UIButton *)sender;
@property (retain, nonatomic) IBOutlet UITextField *textOutlet;
@property(nonatomic,retain) NSMutableArray *mdata;
@end
//
// TWFXViewController.m
// DemoTableView
//
// Created by Lion User on 12-11-27.
// Copyright (c) 2012年 Lion User. All rights reserved.
//
#import "TWFXViewController.h"
@interface TWFXViewController ()
@end
@implementation TWFXViewController
@synthesize mdata;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
/*基础知识
表视图UItableView用来显示表中可见部分的表
表视图单元UITableViewCell负责显示表中的一行
表视图从遵循UITableViewDelegate协议的对象中获取配置数据(配置表视图的外观并处理一些与用户的交互)
表视图从遵循UITableViewDataSource协议的对象中获得行数据
表视图有两种基本样式:分组表(多个Section)和无格式表(单个Section,默认样式)
*/
/*
创建一个NSMutableArray充当数据源
*/
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"0",@"1",@"2",
@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12",
@"13",@"14",@"15",@"16",@"17",@"18",@"19", nil];
//赋值给控制器的属性mdata后,把array release
self.mdata = array;
[array release];
/*
创建一个UITableView,并指定其显示区域和显示样式
style参数指定该表视图的样式,UITableViewStylePlain 表示是无格式表,即只有一个section;
UITableViewStyleGrouped表示分组表,有多个section,若选择此样式,表视图的delegate对象还要实现
numberOfSectionsInTableView: 方法,以指定该表视图有多少个section
*/
UITableView *tableview = [[UITableView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 480.0f)
style:UITableViewStylePlain];
//指定UITableView的数据源对象和委托对象
tableview.dataSource = self;
tableview.delegate = self;
//添加到view显示,然后引用计数器减一
[self.view addSubview: tableview];
[tableview release];
}
/*
UITableView通过该方法得知有多少section
UITableViewDataSource协议里的方法,当UITableView的样式是UITableViewStyleGrouped时需要实现该方法
demo里的UITableView的style是UITableViewStylePlain,所以返回1即可,也可以不现实该方法
*/
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
/*
UITableView通过该方法得知指定的section有多少行
UITableViewDataSource协议里的方法
在demo里,数组里的一项作为一行,所以返回数组的项数即可
*/
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.mdata.count;
}
/*
当表视图需要绘制其中一行时,会调用这个方法,这是 UITableViewDataSource协议里的方法
这个方法详细描述了在绘制cell时的具体信息
参数tableview:表示发出请求的表
参数indexpath:NSIndexPath类型,指明需要绘制的是表视图里的哪个section和哪一行
*/
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//此字符串充当表示 某种 表单元/cell 的键,即是cell一种标识符,也就是表示cell的某种特性
//背景:每个UITableViewCell都是一个对象,都是需要资源开销的.如果数据有有一万条数据,那么系统也要为应用创建一万个cell么?这将要耗费巨大的资源,不现实
//而SimpleTableIdentifier特性表示cell是可重用的(即当表视图滑动时从屏幕上面滚出去的cell会被放到一个可重用队列里,当屏幕底部继续绘制新行时,将优先使用这些cell而不是创建新的cell),这样不管数据源有多少条,程序都只创建有限数量的cell,当屏幕滑动时,那些cell还是以前的那些cell,只不过将显示的数据换了一批而已.大体思想是这样的,具体有点不同,可以自己度娘
static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
//当表视图需要绘制一行时,会优先使用表视图里的可重用队列里的cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
/*
当可重用队列里没有多余的cell后(在程序刚开始运行时,肯定是没有的啦),就只能新建了,
当然,新建的cell也是指定为SimpleTableIdentifier的,同时还要指定新建的cell的style属性
当系统内存紧张时,表视图会删除这些可重用队列里的cell
把新建的cell指定为自动释放
cell的style包括图像 文本 和详细文本三种元素, style参数具体值的说明如下:
UITableViewCellStyleDefault:只显示文本和图片
UITableViewCellStyleValue1:显示文本 图片 和详细文本,详细文本在cell的右边,颜色为浅蓝色
UITableViewCellStyleValue2:只显示文本和详细文本并局中显示,但文本颜色为浅蓝色,并且字体变小颜色为浅蓝色,使用于电话/联系人应用程序
UITableViewCellStyleSubtitle:显示文本 图片 和详细文本,详细文本在文本的下面,颜色为浅灰色
它们具体使用的场合有待度娘
*/
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:SimpleTableIdentifier];
[cell autorelease];
}
//根据表视图的行数,从数组里获取对应索引的数据
NSInteger mRow = [indexPath row];
cell.textLabel.text = [self.mdata objectAtIndex:mRow];
//为每个cell的imageView属性指定一个值,表示在左边显示一张图片
UIImage *image = [UIImage imageNamed:@"Argentina.png"];
cell.imageView.image = image;
//为cell的highlightedImage属性指定一个值,表示当该行被选中时在左边显示的图片将会被换成highlightedImage
UIImage *highlightImage = [UIImage imageNamed:@"Austria.png"];
cell.imageView.highlightedImage = highlightImage;
//为cell添加detailTextLabel属性
if (mRow < 7) {
cell.detailTextLabel.text = @"zou";
} else {
cell.detailTextLabel.text = @"邹";
}
return cell;
}
/*
UITableViewDelegate协议里的方法-----设置行缩进
疑问:UITableView在绘制每一行时都调用此方法?应该是的,但表视图怎么知道有这个方法呢?莫非在为表视图指定delegate对象后,
表视图在进行某一动作时都会根据该动作对应的指定信息来调用相应的方法链?
*/
-(NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
return row;
}
/*
UITableViewDelegate协议里的方法-----处理行的选择
该方法获取传递过来的indexpath,indexpath表示哪项被选中
该方法提供了一个机会给我们来拦截行选中事件?
在行被选中时调用? 行选中这个事件包含里一个方法链,方法链里就包括了这个方法?
*/
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
// NSIndexPath *path = [NSIndexPath indexPathForRow:2 inSection:0];
if (row == 0) {
//返回nil表示没有行被选中
return nil;
}
return indexPath;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
self.mdata = nil;
}
- (IBAction)btnClick:(UIButton *)sender {
if (self.textOutlet.text.length != 0) {
[self.mdata addObject:self.textOutlet.text];
}
if ([self.textOutlet isFirstResponder]) {
[self.textOutlet resignFirstResponder];
}
// [tableview reloadData];
}
- (void)dealloc {
[_textOutlet release];
[mdata release];
// [tableView release];
[super dealloc];
}
@end
对tableview进行编辑:增删改移
/*
实现标记功能
当tableview进入编辑模式时,无法进行标记
*/
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//canAccessoryCell作为标示量,标示是否能标记cell
if (canAccessoryCell) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
/*
UITableViewCell的accessoryType属性表示该行的标记样式,有以下几种常量:
UITableViewCellAccessoryCheckmark //在右边显示一个勾
UITableViewCellAccessoryDetailDisclosureButton //在右边显示一个图标控件
UITableViewCellAccessoryDisclosureIndicator //在右边显示一个 > 图标
UITableViewCellAccessoryNone //不显示任何标记
*/
/*
下面这个函数,使得行的选择效果一闪即消失,即无法选中某行.不是无法标记,而是无法选中,无法突出高亮那种效果
*/
// [tableView deselectRowAtIndexPath:indexPath animated:YES];
}
/*
进入编辑模式后,首先要选则一种模式:删除 \ 增加 \ 移动.
默认是删除模式,既是在行的左边显示一个红色的删除按钮
*/
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
//在demo里,定义了一个属性,该属性保存了当前的编辑模式,在button的 touchupinside 事件里赋值.
return self.editingStyle;
}
/*
进入编辑模式 选择了具体的删除 增加 编辑模式后,执行编辑
*/
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = [indexPath row];
if (self.editingStyle == UITableViewCellEditingStyleDelete) {
/*
在tableview界面上删除和增加记录时,在后台的处理要先操作数据源(删除或增加),然后才调用tableview的删除或增加rows的方法
这涉及到tableview和数据源的底层交互的机制问题,估计是一些映射之类的机制,暂时不清楚
操作完数据源之后,可以调用tableview的删除或增加方法,也可以直接reload数据源,但这样子就没有动画效果了
*/
[self.m_data removeObjectAtIndex:row];
/*
创建一个NSArray数组,里面放的是一组 NSIndexPath 类型 的对象,作为tableview进行操作的对象的索引
*/
NSArray *array = [NSArray arrayWithObjects:indexPath,nil];
[tableView deleteRowsAtIndexPaths:array
withRowAnimation:UITableViewRowAnimationRight];
/*
withRowAtimation参数是一个UITableViewRowAnimation类型的枚举变量,表示该操作对应的动画效果,
一般用UITableViewRowAnimationAutomatic就行了,其他值如下:
typedef enum {
UITableViewRowAnimationFade,
UITableViewRowAnimationRight,
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone,
UITableViewRowAnimationMiddle,
UITableViewRowAnimationAutomatic = 100
} UITableViewRowAnimation;
*/
}
else if(self.editingStyle == UITableViewCellEditingStyleInsert)
{
if (self.textFieldNewData.text.length != 0) {
NSString *newString = self.textFieldNewData.text;
[self.m_data insertObject:newString atIndex:row];
NSArray *array = [NSArray arrayWithObjects:indexPath,nil];
[tableView insertRowsAtIndexPaths:array
withRowAnimation:UITableViewRowAnimationAutomatic];
}
else{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Attention!" message:@"new data is nil!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alertView show];
[alertView release];
}
}
}
/*
是否允许移动cell
*/
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
/*
执行移动操作
只是对数据源执行了移动操作,会自动映射到tableview?
*/
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSUInteger fromRow = [sourceIndexPath row];
NSUInteger toRow = [destinationIndexPath row];
id object = [self.m_data objectAtIndex:fromRow];
[self.m_data removeObjectAtIndex:fromRow];
[self.m_data insertObject:object atIndex:toRow];
}
- (IBAction)btnDone:(UIButton *)sender {
self.editingStyle = UITableViewCellAccessoryNone;
[self.myTableView setEditing:NO];
}
- (IBAction)btnDelete:(UIButton *)sender {
//要先给editingStyle赋值在启动tableview的编辑模式,因为一启动tableview的编辑模式,就会调用 tableview: editingStyleForRowAtIndexPath: 方法来获取当前的编辑模式
self.editingStyle = UITableViewCellEditingStyleDelete;
[self.myTableView setEditing:NO];
[self.myTableView setEditing:YES animated:YES];
}
- (IBAction)btnRemove:(UIButton *)sender {
//移动cell不需要进入 删除 或者 增加 编辑模式
self.editingStyle = UITableViewCellAccessoryNone;
[self.myTableView setEditing:NO];
[self.myTableView setEditing:YES animated:YES];
}
- (IBAction)btnAdd:(UIButton *)sender {
self.editingStyle = UITableViewCellEditingStyleInsert;
[self.myTableView setEditing:NO];
[self.myTableView setEditing:YES animated:YES];
}
- (IBAction)btnSelect:(UIButton *)sender {
if ([self.textFieldNewData isFirstResponder]) {
[self.textFieldNewData resignFirstResponder];
}
if (canAccessoryCell) {
canAccessoryCell = NO;
} else {
canAccessoryCell = YES;
}
}