您的位置:首页 > 产品设计 > UI/UE

iOS:UITableView 使用(一)--基本使用

2014-07-31 22:02 501 查看
===================================================

========================使用========================

参考:--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 shouldtake no arguments and return an NSString object. For example, this could be aname 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布局好;

--3.tableView的delegate的方法如非必要,尽量不要实现:tableView的delegate中的很多函数提供了对cell属性的进一步控制,比如每个cell的高度,cell是否可以编辑,支持的edit风格等,如非必要最好不要实现这些方法因为快速的调用这些方法也会影响性能。如果tableview的一些属性值是固定的(eg:row的高度),直接设置tableview的相应属性(rowHeight),而不是实现代理中的方法(heightForRowAtIndexPath)。
--4.heightForXX方法的优化:尽可能的让这个方法的计算复杂度为 O(1),就是只是简单的从数组中取一个值,然后返回。如果高度是动态计算出来的(一般做法是写个计算行高的类方法,传入那些动态的元素(文字,图片等),然后返回计算后的高度),则采用的方法是"空间换时间"。提前计算高度(服务器接收数据时等),计算完的高度保存起来,用的时候直接取。
--5.tableView:cellForRowAtIndexPath方法中图片的优化:当图片大小跟要显示大小不一样时,如果直接显示的话,对table view的滚动速度也会造成 不容忽视的影响。对图片变形需要对图片做transform,每次压缩图片都要对图片乘以一个变换矩阵,如果你的图片很多,这个计算量是不同忽视的。建议从网络获取的图片后先根据需要显示的图片大小切成合适大小的图,每次只显示处理过大小的图片,当查看大图时在显示大图。如果服务器能直接返回预处理好的小图和图片的大小更好。
备注:使用 Instrument 的 Core Animation 模板可以查看图片的压缩情况。具体查看“相应Instrument文章”。

--6.使用不透明的subView:定制cell的时候,将要添加的subView设置成不透明的会大大减少多个view层叠加时渲染所需要的时间。UIView默认是半透明的

--7.如果可行,直接重载subView的drawRect方法:如果定制cell的过程中需要多个小的元素的话,最好直接对要显示的多个项目进行绘制,而不是采用添加多个subView。

--8.手动 Drawing 视图,绘制 cell 不建议使用UIView,建议使用 CALayer???
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: