UITableView总结
.协议介绍
UITableViewDataSource()
UITableViewDelegate(常用)
.刷新
下拉刷新:
上拉刷新
.搜索
.重用
自定义cell
不使用重用方法
注册Cell
.编辑
滑动更多
.优化
UITableView 总结 UITableView是UIScrollView的子类,因此它可以自动响应滚动事件(一般为上下滚动)。
它内部包含0到多个UITableViewCell对象,每个table cell展示各自的内容。当新cell需要被显示时,就会调用tableView:cellForRowAtIndexPath:方法来获取或创建一个cell;而不可视时,它又会被释放。由此可见,同一时间其实只需要存在一屏幕的cell对象即可,不需要为每一行创建一个cell。 .协议介绍
UITableViewDataSource() //每个section下cell的个数(必须实现)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
//通过indexpath返回具体的cell(必须实现)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; //返回有多少个section(默认是1)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
//每个section上面的标语内容
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
//每个section下面的标语内容
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; // Editing
//是否可编辑
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath; // Moving/reordering
// 是否可拖拽
-tableView:moveRowAtIndexPath:toIndexPath:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath; // Index
//右侧索引条需要的数组内容
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
// return list of section titles to display in section index view (e.g. "ABCD...Z#") //索引值对应的section-index
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1)) // Data manipulation - insert and delete support
// 对Cell编辑后的回调
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath; // 对Cell拖拽后的回调
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
UITableViewDelegate(常用) //将要展示Cell/header/Footer视图回调
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
//完成展示Cell/header/Footer视图回调
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0); // Variable height support
// 每个cell高度的返回(这里高度通过协议返回,是为了table能准确的定位出要显示的Cell-index,从而满足UITableView的重用机制)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
// 每个section-header高度的返回
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
// 每个section-footer高度的返回
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section; // Section header & footer information. Views are preferred over title should you decide to provide both
//可返回每个section-header的自定义视图
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; // custom view for header. will be adjusted to default or specified header height
//可返回每个section-footer的自定义视图
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section; // custom view for footer. will be adjusted to default or specified footer height // Selection // Cell高亮的回调,一般式在选择的时候才高亮
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); // Cell选中和取消选择的回调
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
// Called after the user changes the selection.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
UITableViewDelegate中的协议还有很多,我只列出了比较常用的,想知道更多的可以查看官方头文件或官方文档 分割线:separator 复制粘贴:Copy/Paste 拖拽:move 索引:index 编辑:editing .刷新
下拉刷新: 第三方:EGORefreshTableHeaderView 官方提供(ios6以上系统):UIRefreshControl UIRefreshControl使用方法非常简单: UIRefreshControl * _refresh; ? /******内置刷新的常用属性设置******/
_refresh = [[UIRefreshControl alloc] init];
_refresh.tintColor = [UIColor grayColor];
[_refresh addTarget:self action:@selector(pullToRefresh) forControlEvents:UIControlEventValueChanged]; [_tableView addSubview:_refresh];
另外UITableViewController中已经自带了UIRefreshControl 为成员变量,只需要增加猝发时间就可以了 上拉刷新 .第三方:EGORefreshTableFooterView .自加按钮: - (void) initTableFooterView
{
/******自定义查看更多属性设置******/
if(_bottomRefresh==nil){
_bottomRefresh = [UIButton buttonWithType:UIButtonTypeCustom];
[_bottomRefresh setTitle:LocalizedString(@"c_loading") forState:UIControlStateNormal];
[_bottomRefresh setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
[_bottomRefresh setContentEdgeInsets:UIEdgeInsetsMake(, , , )];
[_bottomRefresh.titleLabel setFont:[UIFont systemFontOfSize:]];
[_bottomRefresh addTarget:self action:@selector(upToRefresh) forControlEvents:UIControlEventTouchUpInside];
_bottomRefresh.frame = CGRectMake(, , , );
_activityView= [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake( , , , )];
[_activityView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
[_activityView stopAnimating];
[_bottomRefresh addSubview:_activityView];
[_bottomRefresh setHidden:YES];
[_tableView setTableFooterView:_bottomRefresh];
}
.视图滚到最后直接加载更多: - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
int contentHeight=scrollView.contentSize.height;
int offsetY=scrollView.contentOffset.y;
if(contentHeight> && offsetY> && offsetY > (contentHeight - scrollView.frame.size.height)){
if(!_isGetMore && !_isNoMore &&!_isUpdate){ //判断是否在加载中或者加载为空,不然或多次加载过多
[self upToRefresh];
}
}
.搜索
在xib中拖入search Bar and Search Display控件,实现UISearchBarDelegate协议 #pragma mark SearchDisplayController DelegateMethod
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self CONTAINS %@", searchString]; if (_searchList)
{
_searchList = nil;
}
_searchList = [NSMutableArray arrayWithArray:[_dataList filteredArrayUsingPredicate:predicate]]; return YES;
} #pragma mark TableView DataSource and Delegate - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return _searchList.count;
}
else
{
return _rowCount;
}
}
demo: https://github.com/Jonear/iosDemo/tree/master/TableViewFresh .重用
UItableView对Cell有一套重用机制,他会将滚出屏幕外的cell放到一个队列中,滚入屏幕的会从这个队列中获取cell,如果没有再去创建。 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellIdentifier = @" cellIdentifier "; UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:windowReuseIdentifier]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:windowReuseIdentifier]; } return cell; } 自定义cell 新建cell文件,继承UITableViewCell 如果你没使用xib或者storyboard的话可以在直接new一个cell,跟普通写法一样 . 新建cell文件,继承UITableViewCell . 如果你没使用xib或者storyboard的话可以在直接new一个cell,跟普通写法一样 static NSString *cellid = @"cellIdentifier";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellid]; if (!cell) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellid];
}
. 如果有xib tic NSString *CellIdentifier = @"FriendCell";
FriendCell *cell= [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
[tableView registerNib:[UINib nibWithNibName:@"FriendCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
.还有个未必好的办法(这个办法也用于在xib多个view中获取到想要的一个) static NSString *reuseId = @"headCell";
NADHeadArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
if (!cell) {
NSArray *nib = [[NSBundle mainBundle]loadNibNamed:@"NADHeadArticleCell" owner:self options:nil];
for(id oneObject in nib){
if([oneObject isKindOfClass:[NADHeadArticleCell class]]){
cell = (NADHeadArticleCell *)oneObject;
break;
}
}
} 不使用重用方法 方法1 将获得cell的方法从- (UITableViewCell*)dequeueReusableCellWithIdentifier:(NSString*)identifier 换为-(UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath 重用机制调用的就是dequeueReusableCellWithIdentifier这个方法,方法的意思就是“出列可重用的cell”,因而只要将它换为cellForRowAtIndexPath(只从要更新的cell的那一行取出cell),就可以不使用重用机制,因而问题就可以得到解决,虽然可能会浪费一些空间。 第一个方法如果使用下面插入多次可能会有问题: NSIndexPath *indexPath = [NSIndexPath indexPathForRow: inSection:];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
方法2 通过为每个cell指定不同的重用标识符(reuseIdentifier)来解决。 重用机制是根据相同的标识符来重用cell的,标识符不同的cell不能彼此重用。于是我们将每个cell的标识符都设置为不同(@"CMainCell%d", indexPath.row) 方法3 删除重用cell的所有子视图 这个方法是通过删除重用的cell的所有子视图,从而得到一个没有特殊格式的cell。 方法4:为不重用的单元格单独生成单独的cell,而不是重用队列中的单元格。 注册Cell // Beginning in iOS 6, clients can register a nib or class for each cell.
// If all reuse identifiers are registered, use the newer -dequeueReusableCellWithIdentifier:forIndexPath: to guarantee that a cell instance is returned.
// Instances returned from the new dequeue method will also be properly sized when they are returned.
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0); - (void)registerNib:(UINib *)nib forHeaderFooterViewReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);
- (void)registerClass:(Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);
简单讲就是注册完cell后,使用 ? dequeueReusableCellWithIdentifier:forIndexPath:
一定会有返回cell,系统在默认没有cell可复用的时候自动new一个cell出来。 .编辑 //是否可编辑
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath; //返回编辑的类型1.没有2.删除3.插入
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath; //删除提示文本
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0); //编辑完成
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
滑动更多 继承UITableViewCell,重新初始化方法
- (void)initializer { int height=self.bounds.size.height;
UIScrollView *cellScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(, , CGRectGetWidth(self.bounds), height)];
cellScrollView.contentSize = CGSizeMake(self.bounds.size.width+BTN_WIDTH, height);
cellScrollView.delegate = self;
cellScrollView.showsHorizontalScrollIndicator = NO;
[cellScrollView setBounces:NO];
[cellScrollView setPagingEnabled:YES]; UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(scrollViewPressed:)];
[cellScrollView addGestureRecognizer:tapGestureRecognizer]; self.cellScrollView = cellScrollView; UIButton * deleteButton=[[UIButton alloc] initWithFrame:CGRectMake(, , BTN_WIDTH, height-)];
[deleteButton setTitle:LocalizedString(@"c_delete") forState:UIControlStateNormal];
[deleteButton setImage:[UIImage imageNamed:@"trash"] forState:UIControlStateNormal];
[deleteButton setImage:[UIImage imageNamed:@"trash"] forState:UIControlStateHighlighted];
[deleteButton.titleLabel setFont:[UIFont systemFontOfSize:]];
[deleteButton setBackgroundColor:color_with_rgb(, , )];
[deleteButton setImageEdgeInsets:UIEdgeInsetsMake(, , , )];
[deleteButton setTitleEdgeInsets:UIEdgeInsetsMake(, , , )];
[deleteButton addTarget:self action:@selector(onDeleteCell) forControlEvents:UIControlEventTouchUpInside];
[self.cellScrollView addSubview:deleteButton]; UIView *scrollViewContentView = [[UIView alloc] initWithFrame:CGRectMake(, , CGRectGetWidth(self.bounds), height)];
scrollViewContentView.backgroundColor = [UIColor whiteColor];
self.scrollViewContentView = scrollViewContentView; [self.cellScrollView addSubview:scrollViewContentView]; UIView *contentViewParent = self;
if (![NSStringFromClass([[self.subviews objectAtIndex:] class]) isEqualToString:@"UITableViewCellContentView"]) {
// iOS 7
contentViewParent = [self.subviews objectAtIndex:];
}
NSArray *cellSubviews = [contentViewParent subviews];
[self insertSubview:cellScrollView atIndex:];
for (UIView *subview in cellSubviews) {
[self.scrollViewContentView addSubview:subview];
} [self insertSubview:self.cellScrollView atIndex:]; }
demo:http://code4app.com/ios/SWTableViewCell/5269d9376803fa5367000001 .优化
.最好改造原生的tableViewCell,尽量不要用xib自定制cell,可以尽量在drawRect中绘制 .尽量使用重用机制,不要创建太多cell .尽量不要使用透明视图,和layer改造 .重载共同部分可以放在生成Cell部分 .尽量不要老调用reloaddata,可能的情况下可以考虑使用 - (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection NS_AVAILABLE_IOS(5_0); - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);
-(void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath NS_AVAILABLE_IOS(5_0);
UITableView总结的更多相关文章
- iOS UITableView 与 UITableViewController
很多应用都会在界面中使用某种列表控件:用户可以选中.删除或重新排列列表中的项目.这些控件其实都是UITableView 对象,可以用来显示一组对象,例如,用户地址薄中的一组人名.项目地址. UITab ...
- UITableView(二)
#import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ...
- iOS: 在UIViewController 中添加Static UITableView
如果你直接在 UIViewController 中加入一个 UITableView 并将其 Content 属性设置为 Static Cells,此时 Xcode 会报错: Static table ...
- iOS 编辑UITableView(根据iOS编程编写)
上个项目我们完成了 JXHomepwner 简单的应用展示,项目地址.本节我们需要在上节项目基础上,增加一些响应用户操作.包括添加,删除和移动表格. 编辑模式 UITableView 有一个名为 e ...
- 使用Autolayout实现UITableView的Cell动态布局和高度动态改变
本文翻译自:stackoverflow 有人在stackoverflow上问了一个问题: 1 如何在UITableViewCell中使用Autolayout来实现Cell的内容和子视图自动计算行高,并 ...
- iOS - UITableView中Cell重用机制导致Cell内容出错的解决办法
"UITableView" iOS开发中重量级的控件之一;在日常开发中我们大多数会选择自定Cell来满足自己开发中的需求, 但是有些时候Cell也是可以不自定义的(比如某一个简单的 ...
- UITableView cell复用出错问题 页面滑动卡顿问题 & 各杂七杂八问题
UITableView 的cell 复用机制节省了内存,但是有时对于多变的自定义cell,重用时会出现界面出错(例如复用出错,出现cell混乱重影).滑动卡顿等问题,这里只简单敲下几点复用出错时的解决 ...
- UITableview delegate dataSource调用探究
UITableview是大家常用的UIKit组件之一,使用中我们最常遇到的就是对delegate和dataSource这两个委托的使用.我们大多数人可能知道当reloadData这个方法被调用时,de ...
- UITableView点击每个Cell,Cell的子内容的收放
关于点击TableviewCell的子内容收放问题,拿到它的第一个思路就是, 方法一: 运用UITableview本身的代理来处理相应的展开收起: 1.代理:- (void)tableView:(UI ...
- 使用UITableView的分组样式
分组样式顾名思义是对TableView中的数据行进行分组处理,每个分组都有一个header和footer. TableView中header的英文文本是大写的,footer的英文文本是小写的.如下图浅 ...
随机推荐
- Selenium(十四):自动化测试模型介绍、模块化驱动测试案例、数据驱动测试案例
1. 自动化测试模型介绍 随着自动化测试技术的发展,演化为了集中模型:线性测试.模块化驱动测试.数据驱动测试和关键字驱动测试. 下面分别介绍这几种自动化测试模型的特点. 1.1 线性测试 通过录制或编 ...
- 【重学Git】整理提交记录
有时候我们在本分支做了一个很小的更改提交,其他分支想直接拿到这个更改提交,有没有一种不像merge或rebase这么正式的做法呢?也就是说:我仅仅是想获取其中一个小改变而已.cherry-pick就是 ...
- Python 中運算子 + 與 * 的 Overload 方法重載功能
字串 String 原本不能像數值一樣有加減乘除運算,但有例外.例如: >>> 'Good' + 'Morning''GoodMorning' 運算子 + 可將2個字串,串接起來. ...
- IDEA使用svn拉取多模块项目
如果没有安装过svn客户端,安装的时候需要选择安装第二个工具,如下图所示 安装小乌龟, 自行搜索, 注意点是需要选择安装第二个工具 因为默认是不安装的, 而这个组件是集成到IDEA ”必须的” . 如 ...
- Undo 相关的等待事件和已知问题 (Doc ID 1575701.1)
Undo Related Wait Events & Known Issues (Doc ID 1575701.1) APPLIES TO: Oracle Database - Enterpr ...
- list集合优化,泛型的使用以及坼箱和装箱
1.list vector线程同步,线程安全arraylist的运行速度较快,因为没有使用线程 LlinkedList以链表结构存储数据 2.泛型泛型类 泛型接口 泛型方法 泛型的属性泛型的属性 属性 ...
- Educational Codeforces Round 76 (Rated for Div. 2)
传送门 A. Two Rival Students 签到. Code /* * Author: heyuhhh * Created Time: 2019/11/13 22:37:26 */ #incl ...
- Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul)
Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul) 1.Eureka Eureka是Netflix的一个子模块,也是核心模块之一.Eureka是 ...
- 8.jenkins 远程管理
远程原理 在我们之前的操作中,是直接将指令写在jenkins 里面的 .因为是做实验.所以指令比较简单. 如果是正式环境的话,可能指令就比较多了. 我们可以将他写成脚本. 我们可以再 jenkins的 ...
- 【使用篇二】SpringBoot使用JdbcTemplate操作数据库(12)
Spring对数据库的操作在jdbc上面做了深层次的封装,提供了JdbcTemplate模板. 在SpringBoot使用JdbcTemplate很简单: 引入数据库驱动包(mysql或oracle) ...