一、UITableView
UITableView基本介绍
UITableView在iOS开发中是应用最为广泛的一种控件。在了解UITableView之前,首先看一下iOS开发中UI控件的组织结构:
UI控件组织结构从上图中可以看出,UITableView它的继承关系是:
tableView继承关系因此UITableView可以响应事件、支持垂直滚动,⽽且性能极佳 。
UITableView的结构
UITableView的结构如下图所示:
tableView结构图可以看出:
一个tableView = 一个tableView HeaderView + 若干个section + 一个tableView FooterView;
一个section = 一个section HeaderView + 若干个cell + 一个section FooterView ;
UITableView的初始化方法为:
// 设置表的大小、位置以及样式
//(style:包括plain和group)
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style;
//或者用UIView的初始化方法,设置表的大小和位置
- (instancetype)initWithFrame:(CGRect)frame;
UITableView的风格
UITableViewStyle
是一个枚举,有两种样式:
UITableViewStylePlain
和 UITableViewStyleGrouped
:
typedef NS_ENUM(NSInteger, UITableViewStyle) {
UITableViewStylePlain, // 标准的表视图样式
UITableViewStyleGrouped // 分组的表视图样式
};
两种样式如下图所示:
tableView风格UITableView的属性
常用的属性有:
// 获取表视图的样式(plain和group)
@property (nonatomic, readonly) UITableViewStyle style;
// 可设置UITableViewDataSource的代理
@property (nonatomic, weak, nullable) id <UITableViewDataSource> dataSource;
// 可设置UITableViewDelegate的代理
@property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;
// tableView的行高、组头试图、组尾视图的高度,未设置时,返回默认值:-1.0
// 当与代理方法同时实现时,按照代理方法中的高度进行设置
@property (nonatomic) CGFloat rowHeight;
@property (nonatomic) CGFloat sectionHeaderHeight;
@property (nonatomic) CGFloat sectionFooterHeight;
// 性能优化(如果实现),估计tableView的行高、组头试图、组尾视图的高度,未设置时,返回默认值:0.0
//在显示的时候回去调用heightForRowAtIndexPath,真正开始计算
@property (nonatomic) CGFloat estimatedRowHeight;
@property (nonatomic) CGFloat estimatedSectionHeaderHeight;
@property (nonatomic) CGFloat estimatedSectionFooterHeight;
// section的个数
@property (nonatomic, readonly) NSInteger numberOfSections;
// 返回可见的cells
@property (nonatomic, readonly) NSArray<__kindof UITableViewCell *> *visibleCells;
// 返回可见的位置
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForVisibleRows;
// 设置背景视图,只能写入,可根据tableView 的大小进行自动调整
@property (nonatomic, strong, nullable) UIView *backgroundView
/*
* 编辑相关(Editing)
*/
// 是否允许编辑,默认是NO
@property (nonatomic, getter=isEditing) BOOL editing;
- (void)setEditing:(BOOL)editing animated:(BOOL)animated;
// 在非编辑下,行是否可以选中,默认为YES
@property (nonatomic) BOOL allowsSelection;
// 在编辑模式下,行是否可以选中,默认为NO
@property (nonatomic) BOOL allowsSelectionDuringEditing;
// 在非编辑模式下,是否允许同时选择多行,默认为NO
@property (nonatomic) BOOL allowsMultipleSelection;
// 在编辑模式下,是否允许同时选择多行,默认为NO
@property (nonatomic) BOOL allowsMultipleSelectionDuringEditing;
/*
* 选择相关(Selection)
*/
// 返回选定cell所对应的indexPath,单行,未选中时返回nil
@property (nonatomic, readonly, nullable) NSIndexPath *indexPathForSelectedRow;
// 返回选定cells所对应的indexPath集合,多行,未选中时返回nil
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForSelectedRows;
/*
* 显示相关(Appearance)
*/
// 指定当tableView中多少行的时候开始显示IndexList,
// 默认的设置是NSIntegerMax,即默认是不显示indexList的
@property (nonatomic) NSInteger sectionIndexMinimumDisplayRowCount;
// 索引号颜色
@property (nonatomic, strong, nullable) UIColor *sectionIndexColor;
// 索引号背景颜色(未触摸/点击时显示的背景颜色)
@property (nonatomic, strong, nullable) UIColor *sectionIndexBackgroundColor;
// 跟踪索引号背景颜色(触摸/点击时显示的背景颜色)
@property (nonatomic, strong, nullable) UIColor *sectionIndexTrackingBackgroundColor;
// cell之间分隔线的样式(默认是UITableViewCellSeparatorStyleSingleLine)
@property (nonatomic) UITableViewCellSeparatorStyle separatorStyle;
// cell的分割线的偏移。(UIEdgeInsets中的right、left起作用???)
@property (nonatomic) UIEdgeInsets separatorInset;
// cell之间的分割线颜色(默认是灰色)
@property (nonatomic, strong, nullable) UIColor *separatorColor;
// 设置毛玻璃效果
@property (nonatomic, copy, nullable) UIVisualEffect *separatorEffect;
// if cell margins are derived from the width of the readableContentGuide.
@property (nonatomic) BOOL cellLayoutMarginsFollowReadableWidth;
// 设置headerView
@property (nonatomic, strong, nullable) UIView *tableHeaderView;
// 设置footerView
@property (nonatomic, strong, nullable) UIView *tableFooterView;
// 记住上次的选择
@property (nonatomic) BOOL remembersLastFocusedIndexPath;
UITableView的方法
// 表格进入编辑状态,是否有动画
- (void)setEditing:(BOOL)editing animated:(BOOL)animated;
/*
* 数据相关(Data)
*/
// 刷新整个表视图
- (void)reloadData;
// 刷新索引栏
- (void)reloadSectionIndexTitles
/*
* 信息相关(Info)
*/
// 获取某个组有多少行
- (NSInteger)numberOfRowsInSection:(NSInteger)section;
//根据section或indexPath获得section、headerView、footerView、row对应的CGRect
// 获取某个组的位置和大小(包括头尾试图和所有行)
- (CGRect)rectForSection:(NSInteger)section
// 取某个组的头视图的位置和大小
- (CGRect)rectForHeaderInSection:(NSInteger)section;
// 取某个组的尾视图的位置和大小
- (CGRect)rectForFooterInSection:(NSInteger)section;
// 获取某一行的位置和大小
- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath;
// 根据point、cell或rect获得indexPath
// 根据某一点,返回indexPath(如果点不在tableView的任何一行上,则返回nil)
- (nullable NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point;
// 获取单元格的IndexPath信息(如果cell不可见,则返回nil)
- (nullable NSIndexPath *)indexPathForCell:(UITableViewCell *)cell;
// 返回某个区域内 多个单元格信息(如果rect无效,则返回nil)
- (nullable NSArray<NSIndexPath *> *)indexPathsForRowsInRect:(CGRect)rect;
// 通过单元格的indexPath得到单元格
- (nullable __kindof UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath;
// 获得头视图(可进行头视图设置)
- (nullable UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section;
// 获得尾视图(可进行尾视图设置)
- (nullable UITableViewHeaderFooterView *)footerViewForSection:(NSInteger)section;
/*
* 插入、删除、更新、移动
*/
// 二者配合使用
//添加或删除前必须调用,只添加或删除才会更新行数
- (void)beginUpdates;
// 添加或删除后必须调用,只添加或删除方法时才会更新
- (void)endUpdates;
//对section进行插入、删除、更新、移动操作
// 插入一个或多个section,并使用动画
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
// 删除一个或多个section,并使用动画
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
// 更新一个或多个section,并使用动画
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
// 移动某一个section到目标section位置
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;
//对row进行插入、删除、更新、移动操作
// 插入一个或多个row,并使用动画
- (void)insertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
// 删除一个或多个row,并使用动画
- (void)deleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
// 更新一个或多个row,并使用动画
- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
// 移动某一个row到目标row位置
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath NS_AVAILABLE_IOS(5_0);
/*
* 选择相关
*/
// 设置选中某个区域内的单元格
- (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;
// 取消选中的单元格
- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;
/*
* 重用机制
*/
// 获取重用队列里的cell,代理调用
- (nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;
- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
- (nullable __kindof UITableViewHeaderFooterView *)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier
/*
* 注册
*/
// 注册cell
// 注册xib文件自定义的cell
- (void)registerNib:(nullable UINib *)nib forCellReuseIdentifier:(NSString *)identifier;
// 注册纯代码自定义的cell
- (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier;
// 注册header,footer
// 注册xib文件自定义的header,footer
- (void)registerNib:(nullable UINib *)nib forHeaderFooterViewReuseIdentifier:(NSString *)identifier;
// 注册xib文件自定义的header,footer
- (void)registerClass:(nullable Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier;
2、UITableView的代理
我们发现单元格高度、分组标题高度以及尾部说明的高度都需要调整,此时就需要使用代理方法。UITableView代理方法有很多,例如监听单元格显示周期、监听单元格选择编辑操作、设置是否高亮显示单元格、设置行高等:
// 将要展示的cell会回调(可以在其中对cell进行修改设置)
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
// 将要展示的headView会回调
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section;
// 将要展示的headView会回调
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section;
// 完成视图展示时回调,此时已经在界面上了
// 完成展示的cell时,会回调
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath;
// 完成展示的headerView时,会回调
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section;
// 完成展示的footerView时,会回调
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section;
/*
* 高度设置相关
*/
// 设置cell高度(这里高度通过协议返回,是为了table能准确的定位出要显示的Cell-index,从而满足UITableView的重用机制))
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
// 设置headerView高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
// 设置footerView高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
//性能优化(如果实现),加载的时候使用的是本方法,由于是一个固定的值,不需要计算,所以加载速度回很快,在显示的时候回去调用heightForRowAtIndexPath,真正开始计算。
// row的估计高度
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;
// header的估计高度
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section;
// footer的估计高度
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section;
/*
* 自定义section的头尾视图相关
*/
//可设置每个section-header和 footer 的自定义视图
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
/*
* row的 Accessoriy 相关
*/
// 可设置cell上Accessory的类型accessaryType(共5种)
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath;
// 设置cell上右指向Accessory的响应方法(当cell的accessaryType为UITableViewCellAccessoryDetailDisclosureButton时,
// 点击accessaryView将会调用delegate的tableView:accessoryButtonTappedForRowWithIndexPath方法。否则只是didSelectRowAtIndexPath;)
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;
/*
* 选择(selection)相关
*/
// 是否高亮
// cell高亮回调,一般在选中的时候高亮
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath;
// cell一直高亮
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath;
// cell选中时不高亮
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath;
/* 先点击row0,再点击row1,俩着执行顺序(在下一行将要选中后才取消上一行的选中 ):
willSelectRowAtIndexPath 当前row为:0
didSelectRowAtIndexPath 当前row为:0
willSelectRowAtIndexPath 当前row为:1
willDeselectRowAtIndexPath 当前row为:0
didDeselectRowAtIndexPath 当前row为:0
didSelectRowAtIndexPath 当前row为:1
*/
// 用户选择之前调用,将要选中
- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
// 将要取消选中(此时已选中下一个row)
- (nullable NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath;
// 用户选中时调用,已经选中当前行
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
// 用户选择之后调用,取消选中(已经选中当前row)
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath;
/*
* 编辑(editing)相关
*/
// 返回编辑的类型1.没有2.删除3.插入
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
// 删除提示文本(删除确认按钮上的标题文字)
- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
// 左滑小菜单 可以自定义想要的编辑操作 (要求ios8以上)
- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
// 编辑模式下,cell是否需要缩进,默认是YES(缩进),否则使用NO(只对grouped的TableView有效。)
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// 用于设置缩进的级别
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath;
// 编辑状态发生改变时调用
// 指定cell开始编辑时调用
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// 指定cell编辑完成时调用
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(nullable NSIndexPath *)indexPath
/*
* 复制(copy)相关
*/
// 复制的时候三个方法都必须实现
// 是否将要显示指定cell的菜单
- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath;
// 是否能使用 sender 对指定cell进行执行操作
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender;
//通过 sender 对指定cell执行操作
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender;
/*
* 移动(move)再排序相关
*/
// 移动row时执行(将一个指定cell从source处移动到proposed(提议的)目标处 )
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;
3、UITableView的数据源
由于iOS是遵循MVC模式设计的,很多操作都是通过代理和外界沟通的,但对于数据源控件除了代理还有一个数据源属性,通过它和外界进行数据交互。
数据源:(一般为控制器)根据索引路径(indexPath:可以定位到唯一的一个单元格)为某一个单元格提供数据。
索引路径:(NSIndexpath)拥有两个属性section(段)、row(行),通过这两个属性即可定位UITableView中的唯一一个单元格cell
对于UITableView设置完dataSource(tableView.dataSource=self
)后,需要实现UITableViewDataSource
协议:
下面两个代理方法必须实现:
@required //必须实现
//每个section下行数(必须实现)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
//通过indexpath返回cell的具体样式和内容(必须实现)
//可以在这里对cell进行设置(*这里使用了可以重复利用 UITableViewCell 的机制*)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
@optional //其他的代理方法可选实现:
//返回分组section数,默认是1
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
/*
* 头尾标题内容(_字体样式固定,可以通过UILable改变_)
*/
//返回每个section头标题内容
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
//返回每个section尾部标题说明
-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
/*
* 索引相关
*/
//返回每个section标题索引(可以在这里设置索引)
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
//点击索引触发(告诉tableView哪个section将会响应点击的索引
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index;
/*
* 编辑相关
*/
//是否可编辑
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
// 是否可拖拽(使用代理方法`tableView:moveRowAtIndexPath:toIndexPath:`之前设置)
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
//插入/删除指定数据(根据编辑风格`editingStyle`确定是插入还是删除)
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
//重新排序/移动数据操作
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
cell的编辑风格UITableViewCellEditingStyle是个结构体,共有三个元素:没有风格、删除、插入:
typedef NS_ENUM(NSInteger, UITableViewCellEditingStyle) {
UITableViewCellEditingStyleNone,
UITableViewCellEditingStyleDelete,
UITableViewCellEditingStyleInsert
};
二、UITableViewCell基本介绍
UITableViewCell的结构
从上图中可以看到,在UITableView中数据只有行的概念,并没有列的概念,其中每行数据都是一个UITableViewCell。下图是UITableViewCell内置好的控件,可以看见contentView控件作为父控件,里面包括两个UILabel控件(textLabel,detailTextLabel),一个UIImage控件(imageView),一个AccessoryView,分别用于容器、显示内容、图片和详情(当然,这些子控件并不一定要全部使用):
tableViewCell结构图UITableViewCell的示意图为:
tableViewCell示意图UITableViewCell的风格
UITableViewCell有四种风格,根据不同的分格,各个控件会进行不同的分布。四种风格分别为:
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
UITableViewCellStyleDefault, //左侧显示textLabel,不显示detailTextLabel,imageView可选(显示在最左边)
UITableViewCellStyleValue1, //左侧显示textLabel,右侧显示detailTextLabel,imageView可选(显示在最左边)
UITableViewCellStyleValue2, //左侧依次显示textLabel和detailTextLabel,不显示imageView
UITableViewCellStyleSubtitle //左上方显示textLabel,左下方显示detailTextLabel,imageView可选(显示在最左边)
};
UITableViewCellAccessoryType
UITableViewCell中还可显示accessoryView(辅助指示视图),位于UITableViewCell的最右边,accessaryView的样式UITableViewCellAccessoryType有五种:
typedef NS_ENUM(NSInteger, UITableViewCellAccessoryType) {
UITableViewCellAccessoryNone, //没有视图
UITableViewCellAccessoryDisclosureIndicator, //箭头
UITableViewCellAccessoryDetailButton //button
UITableViewCellAccessoryDetailDisclosureButton, //button和箭头
UITableViewCellAccessoryCheckmark, //对勾
};
当然,我们也可以通过cell的accessoryView属性来自定义辅助指示视图(比如往右边放一个开关)。
3、自定义UITableViewCell加载:代码&xib
代码自定义
方法一:(使用重用机制alloc一个cell,IDENTIFIER作为重用机制查找的标识)
#define IDENTIFIER @"identifier"
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* cell = nil;
//使用重用机制,IDENTIFIER作为重用机制查找的标识,tableview查找可用cell时通过IDENTIFIER检索,如果有则cell不为nil
cell = [tableView dequeueReusableCellWithIdentifier:IDENTIFIER];
if (cell == nil) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:IDENTIFIER];//代码创建的cell需要使用该初始化方法
}
return cell;
}
==注意:以上方式要注意cell创建时的Identifier与tableview dequeueReusableCell时是一样的。==
方法二:(首先在viewdidload中调用registerClass注册cell)
#define IDENTIFIER @"identifier"
首先在viewdidload中注册cell
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[TableViewCell class] forCellReuseIdentifier:IDENTIFIER];
}
// 然后在tableview的delegate中
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:IDENTIFIER];
//这里会发现,cell一直都不是nil,不再需要创建
if (cell == nil) {
NSLog(@"cell create at row:%ld", (long)indexPath.row);
}
return cell;
}
==通过注册cell类的方式,tableView dequeueReusableCellWithIdentifier 总是有值,即让tableview自己加载,不再需要手动创建cell,UICollectionViewCell也是类似。==
xib自定义
方法一:(代理方法中调用 loadNibNamed方法)
#define IDENTIFIER @"identifier"
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:IDENTIFIER];
if (cell == nil) {
cell = [[NSBundle mainBundle] loadNibNamed:@"TableViewCell" owner:nil options:nil].firstObject;
NSLog(@"cell create at row:%ld", (long)indexPath.row);//此处要使用loadnib方式!
}
NSNumber* number = self.array[indexPath.row];
cell.textLabel.text = number.stringValue;
return cell;
}
==注意:TableviewCell为xib的名字,xib中的identifier必须与代码中的IDENTIFIER定义相同。==
方法二:(首先在viewdidload中调用registerNib注册cell)
#define IDENTIFIER @"identifier"
// 首先在viewdidload中注册cell
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:@"TableViewCell" bundle:nil] forCellReuseIdentifier:IDENTIFIER];
}
// 然后在tableview的delegate中
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:IDENTIFIER];
if (cell == nil) {
//这里会发现,cell一直都不是nil,不再需要创建
NSLog(@"cell create at row:%ld", (long)indexPath.row);
}
return cell;
}
==通过注册cell类的方式,让tableview自己加载,不再需要手动创建cell。==
网友评论