===================================================
========================使用========================
参考:--developer:tableview Sample Code(TableViewSuite);
------------------------最基本------------
1.创建tableview:
_tableView = [[UITableView alloc]initWithFrame:self.view.bounds];
_tableView.dataSource = self;
_tableView.delegate = self;
[self.view addSubview:_tableView];
注意:如果控制器是继承UITableViewController,则以上代码不用写,它本身自带tableview,并且相关配置也可好,直接重写相关代理方法即可。
2.实现相关代理方法 代码方式
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.xxArray count]; //default numOfSection is one
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = @"simpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [self.xxArray objectAtIndex:indexPath.row];
return cell;
}
xib方式
如果tableview是在xib中创建,则可以它里面add一个tableViewCell(创建了一个Prototype Cells),则cellForRowAtIndexPath可以简单点写():
注意cell的identify一定要对应上。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
// Set up the cell.
cell.textLabel.text = [self.xxArray objectAtIndex:indexPath.row];
return cell;
}
------注意:
1.tableview创建的时候必须指定UITableViewStyle,如果用-initWithFrame: 那么会自动calls this with UITableViewStylePlain;默认的Style为UITableViewStylePlain;
2.上面俩个方法是@protocol UITableViewDataSource中@required的俩个方法,其他根据要求实现。
------------------------sectioned------------
注意数据源 数组sectionsArray(regions)的一般结构: 里面包含不同section对象(APLRegion),同时每个section对象(APLRegion)有自己的属性、名字,包含不同的row(APLTimeZoneWrapper).
NSArray *knownTimeZoneNames = [NSTimeZone knownTimeZoneNames]; // 所有的列
//要生成的 sectionsArray
NSMutableArray *regions = [[NSMutableArray alloc] initWithCapacity:[knownTimeZoneNames count]];
//将所有的列 划分为不同的section,每一列归属到不同的section下
for (NSString *timeZoneName in knownTimeZoneNames) {
NSArray *nameComponents = [timeZoneName componentsSeparatedByString:@"/"];
NSString *regionName = [nameComponents objectAtIndex:0];
// 提取sections-- 如section存在,不处理;不存在,创建之。
APLRegion *region = nil;
for (APLRegion *aRegion in regions) {
if ([aRegion.name isEqualToString:regionName]) {
region = aRegion;
break;
}
}
if (region == nil) {
region = [[APLRegion alloc] initWithName:regionName];
[regions addObject:region];
}
// 将不同的列添加到不同的section下
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:timeZoneName];
APLTimeZoneWrapper *timeZoneWrapper = [[APLTimeZoneWrapper alloc] initWithTimeZone:timeZone nameComponents:nameComponents];
[region addTimeZoneWrapper:timeZoneWrapper];
}
// 对不同的section排序,以及section包含的列排序
NSSortDescriptor *localeNameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"localeName" ascending:YES comparator:^(id name1, id name2) {
return [(NSString *)name1 localizedStandardCompare:(NSString *)name2];
}];
for (APLRegion *aRegion in regions) {
[aRegion.mutableTimeZoneWrappers sortUsingDescriptors:@[localeNameSortDescriptor]];
}
…… //section排序
//得到结构 sectionsArray
return regions;
相关头文件:注意上文中
生成sectionsArray的代码是在APLRegion.h 类中方法(knownRegions)返回,而不是在使用tableview的控制器中生成。
// APLRegion.h
@interface APLRegion : NSObject
@property (nonatomic, copy) NSString *name;
- (NSArray *)timeZoneWrappers;
+ (NSArray *)knownRegions;
// APLTimeZoneWrapper.h
@interface APLTimeZoneWrapper : NSObject
@property (nonatomic, copy) NSString *localeName;
@property (nonatomic) NSTimeZone *timeZone;
- (instancetype)initWithTimeZone:(NSTimeZone *)aTimeZone nameComponents:(NSArray *)nameComponents;
------------------------用UILocalizedIndexedCollation创建索引------------
--简介:UILocalizedIndexedCollation 对含有section index 的tableview 的数据可以非常方便的进行归类、排序。
创建UILocalizedIndexedCollation对象
self.collation = [UILocalizedIndexedCollation currentCollation]; //[... currentCollation]方法每次返回的对象不是同一个
sectionTitles 和 sectionIndexTitles
属性 只读,表示所有
section的标题和索引的,用作titleForHeaderInSection 、sectionIndexTitlesForTableView
@property(nonatomic, readonly) NSArray *sectionTitles;
@property(nonatomic, readonly) NSArray *sectionIndexTitles;
下面是对
tableview 的model object 进行归类、排序。
NSInteger index, sectionTitlesCount = [[self.collation sectionTitles] count];
//创建sectionsArray,其中数组里每一项是一个数组,表示一个section。其实也可以像上文一样存APLRegion对象,表示一个section
NSMutableArray *newSectionsArray = [[NSMutableArray alloc] initWithCapacity:sectionTitlesCount];
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *array = [[NSMutableArray alloc] init];
[newSectionsArray addObject:array];
}
// 对model object 进行归类
for (APLTimeZoneWrapper *timeZone in self.timeZonesArray) {
NSInteger sectionNumber = [self.collation sectionForObject:timeZone collationStringSelector:@selector(localeName)];
NSMutableArray *sectionTimeZones = newSectionsArray[sectionNumber];
[sectionTimeZones addObject:timeZone];
}
// 对每个section的model object排序.
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *timeZonesArrayForSection = newSectionsArray[index];
// If the table view or its contents were editable, you would make a mutable copy here.
NSArray *sortedTimeZonesArrayForSection = [self.collation sortedArrayFromArray:timeZonesArrayForSection collationStringSelector:@selector(localeName)];
newSectionsArray[index] = sortedTimeZonesArrayForSection;
}
self.sectionsArray = newSectionsArray;
说明,sectionForObject:collationStringSelector方法是
identifying the section in which a model object belongs。sortedArrayFromArray:collationStringSelector方法是
Sorts the objects within a section。排序依据为参数selector 为
identifies a method returning an identifying string for object that is used in collation / each object in array. The method should
take no arguments and return an NSString object. For example, this could be a
name propertyon the object.
另外,索引的跳转关系sectionForSectionIndexTitleAtIndex
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [self.collation sectionForSectionIndexTitleAtIndex:index];
}
======================================================
========================定制cell========================
1.通过cell的subviews:代码里在cell的contentView添加subViews,详见下图;或者(当tableview在xib中创建的情况方便)在xib中创建cell(往tableview中add一个tableviewcell,注意identify),添加cell的subview,详见上面“基本使用 2步中的xib方式”。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
……
[cell.contentView addSubview:label];
……
}
2.从UITableViewCell派生一个类:
通过从UITableViewCell中派生一个类,可以更深度的定制一个cell,可以指定cell在进入edit模式的时候如何相应等等。
--a.通过cell的subviews:在代码中将相应的subView添加到contentView;或者建立类自己的xib / 在tableview的xib中中创建cell(注意identify),配置xib,创建的时候cell通过NSBundle /dequeueReusableCellWithIdentifier:方法创建。
--b.通过drawRect方法:将所有要绘制的内容放到一个定制的subView中,并且重载该subView的drawRect方法直接把要显示的内容绘制出来(这样可以避免subView过多导致的性能瓶颈),最后再将该subView添加到cell派生类中的contentView中即可。但是这样定制的cell需要注意在数据改变的时候,通过手动调用该subView的setNeedDisplay方法来刷新界面,这个例子可以在苹果的帮助文档中的TableViewSuite工程中找到。
备注:
1.上面两种定制cell的方法,我们会发现subView都是添加在cell的contentView上面的,而不是直接加到cell上面,这样写也是有原因的。参考文章<UITableviewCell> 。
----------------------------自定义accessoryView------------
--如果accessoryView为UIControl子类(比如button),当点击某个accessoryView的时候,如何区别该accessoryView是哪个indexPath的row?
注意俩点:1.button点击方法可以添加2个参数(event);2.tableview的indexPathForRowAtPoint 方法;
[button addTarget:self action:@selector(btnClicked:event:) forControlEvents:UIControlEventTouchUpInside];
//俩点:1.给button的点击方法添加event参数,获取点击的position,之后利用tableview的indexPathForRowAtPoint方法得到indexPath;
- (void)btnClicked:(id)sender event:(id)event{
NSSet *touches =[event allTouches];
UITouch *touch =[touches anyObject];
CGPointcurrentTouchPosition = [touch locationInView:self.tableView];
NSIndexPath *indexPath= [self.tableView indexPathForRowAtPoint:currentTouchPosition];
if (indexPath!= nil){
[self tableView: self.tableView accessoryButtonTappedForRowWithIndexPath:indexPath];
}
}
===================================================
==================tableView性能优化==================
--1.重用cell;
--2.避免content的重新布局:尽量避免在重用cell时候,对cell的重新布局,一般情况在在创建cell的时候就将cell布局好;
--6.使用不透明的subView:定制cell的时候,将要添加的subView设置成不透明的会大大减少多个view层叠加时渲染所需要的时间。UIView默认是半透明的。
--7.如果可行,直接重载subView的drawRect方法:如果定制cell的过程中需要多个小的元素的话,最好直接对要显示的多个项目进行绘制,而不是采用添加多个subView。
--8.手动 Drawing 视图,绘制 cell 不建议使用UIView,建议使用 CALayer???