博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UITableView总结
阅读量:5166 次
发布时间:2019-06-13

本文共 15069 字,大约阅读时间需要 50 分钟。

 

 

摘要 UITableView

 

 

目录[-]

UITableView 总结

 

UITableView是UIScrollView的子类,因此它可以自动响应滚动事件(一般为上下滚动)。

它内部包含0到多个UITableViewCell对象,每个table cell展示各自的内容。当新cell需要被显示时,就会调用tableView:cellForRowAtIndexPath:方法来获取或创建一个cell;而不可视时,它又会被释放。由此可见,同一时间其实只需要存在一屏幕的cell对象即可,不需要为每一行创建一个cell。

 

1.协议介绍

UITableViewDataSource(11)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//每个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(常用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//将要展示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

2.刷新

下拉刷新:

第三方:EGORefreshTableHeaderView

官方提供(ios6以上系统):UIRefreshControl

UIRefreshControl使用方法非常简单:

UIRefreshControl  * _refresh;

1
2
3
4
5
6
 
/******内置刷新的常用属性设置******/
    
_refresh = [[UIRefreshControl alloc] init];
_refresh.tintColor = [UIColor grayColor];
[_refresh addTarget:self action:@selector(pullToRefresh) forControlEvents:UIControlEventValueChanged];
  
[_tableView addSubview:_refresh];

 

另外UITableViewController中已经自带了UIRefreshControl  为成员变量,只需要增加猝发时间就可以了

上拉刷新

1.第三方:EGORefreshTableFooterView

2.自加按钮:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (
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(0, 0, 5, 0)];
        
[_bottomRefresh.titleLabel setFont:[UIFont systemFontOfSize:15]];
       
[_bottomRefresh addTarget:self action:@selector(upToRefresh) forControlEvents:UIControlEventTouchUpInside];
       
_bottomRefresh.frame = CGRectMake(0, 0, 320, 44);
       
_activityView= [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(90 , 3, 30, 30)];
       
[_activityView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
       
[_activityView stopAnimating];
       
[_bottomRefresh addSubview:_activityView];
       
[_bottomRefresh setHidden:YES];
       
[_tableView setTableFooterView:_bottomRefresh];
    
}

 

3.视图滚到最后直接加载更多:

1
2
3
4
5
6
7
8
- (
void
)scrollViewDidScroll:(UIScrollView *)scrollView {
    
int 
contentHeight=scrollView.contentSize.height;
    
int 
offsetY=scrollView.contentOffset.y;
    
if
(contentHeight>0 && offsetY>0  && offsetY > (contentHeight - scrollView.frame.size.height)){
       
if
(!_isGetMore && !_isNoMore &&!_isUpdate){ 
//判断是否在加载中或者加载为空,不然或多次加载过多
           
[self upToRefresh];
       
}
    
}

 

3.搜索

   在xib中拖入search Bar and Search Display控件,实现UISearchBarDelegate协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#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: 

4.重用

UItableView对Cell有一套重用机制,他会将滚出屏幕外的cell放到一个队列中,滚入屏幕的会从这个队列中获取cell,如果没有再去创建。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *cellIdentifier = @" cellIdentifier ";

   

    UITableViewCell * cell = [tableViewdequeueReusableCellWithIdentifier:windowReuseIdentifier];

        if (!cell) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:windowReuseIdentifier];

        }

    return cell;

}   

自定义cell

新建cell文件,继承UITableViewCell

如果你没使用xib或者storyboard的话可以在直接new一个cell,跟普通写法一样

1.    新建cell文件,继承UITableViewCell

2.    如果你没使用xib或者storyboard的话可以在直接new一个cell,跟普通写法一样

1
2
3
4
5
6
static 
NSString *cellid = @
"cellIdentifier"
;
    
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellid];
      
    
if 
(!cell) {
        
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellid];
    
}

 

3. 如果有xib

1
2
3
4
5
6
static 
NSString *CellIdentifier = @
"FriendCell"
;
        
FriendCell *cell= [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        
if 
(!cell) {
            
[tableView registerNib:[UINib nibWithNibName:@
"FriendCell" 
bundle:nil] forCellReuseIdentifier:CellIdentifier];
            
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        
}

 

4.还有个未必好的办法(这个办法也用于在xib多个view中获取到想要的一个)

1
2
3
4
5
6
7
8
9
10
11
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),就可以不使用重用机制,因而问题就可以得到解决,虽然可能会浪费一些空间。

 第一个方法如果使用下面插入多次可能会有问题:

1
2
 
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

 

方法2 通过为每个cell指定不同的重用标识符(reuseIdentifier)来解决。

重用机制是根据相同的标识符来重用cell的,标识符不同的cell不能彼此重用。于是我们将每个cell的标识符都设置为不同(@"CMainCell%d", indexPath.row)

 

方法3 删除重用cell的所有子视图

这个方法是通过删除重用的cell的所有子视图,从而得到一个没有特殊格式的cell。

 

方法4:为不重用的单元格单独生成单独的cell,而不是重用队列中的单元格。

注册Cell

1
2
3
4
5
6
7
8
// 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后,使用

1
dequeueReusableCellWithIdentifier:forIndexPath:

 

一定会有返回cell,系统在默认没有cell可复用的时候自动new一个cell出来。

5.编辑

1
2
3
4
5
6
7
8
9
10
11
//是否可编辑
- (
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,重新初始化方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
- (
void
)initializer {
  
    
int 
height=self.bounds.size.height;
    
UIScrollView *cellScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 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(320, 0, BTN_WIDTH, height-3)];
    
[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:12]];
    
[deleteButton setBackgroundColor:color_with_rgb(211, 49, 49)];
    
[deleteButton setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 15)];
    
[deleteButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
    
[deleteButton addTarget:self action:@selector(onDeleteCell) forControlEvents:UIControlEventTouchUpInside];
    
[self.cellScrollView addSubview:deleteButton];
     
    
UIView *scrollViewContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), height)];
    
scrollViewContentView.backgroundColor = [UIColor whiteColor];
    
self.scrollViewContentView = scrollViewContentView;
     
    
[self.cellScrollView addSubview:scrollViewContentView];
     
    
UIView *contentViewParent = self;
    
if 
(![NSStringFromClass([[self.subviews objectAtIndex:0] 
class
]) isEqualToString:@
"UITableViewCellContentView"
]) {
        
// iOS 7
        
contentViewParent = [self.subviews objectAtIndex:0];
    
}
    
NSArray *cellSubviews = [contentViewParent subviews];
    
[self insertSubview:cellScrollView atIndex:0];
    
for 
(UIView *subview in cellSubviews) {
        
[self.scrollViewContentView addSubview:subview];
    
}
     
    
[self insertSubview:self.cellScrollView atIndex:0];
     
}

 

   demo:

6.优化

1.最好改造原生的tableViewCell,尽量不要用xib自定制cell,可以尽量在drawRect中绘制

2.尽量使用重用机制,不要创建太多cell

3.尽量不要使用透明视图,和layer改造

4.重载共同部分可以放在生成Cell部分

5.尽量不要老调用reloaddata,可能的情况下可以考虑使用

1
2
3
4
5
6
7
8
9
- (
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);

转载于:https://www.cnblogs.com/helinzi/p/4436308.html

你可能感兴趣的文章
类模板使用说明
查看>>
Redis源代码分析(一)--Redis结构解析
查看>>
Flex父子窗体相互调用
查看>>
改动网卡IP信息
查看>>
【Java】国内maven私服
查看>>
第三方开源水面波浪波形view:WaveView
查看>>
POJ 2251 Dungeon Master(3D迷宫 bfs)
查看>>
Linux查看和编辑文件
查看>>
MVC之 自定义过滤器(Filter)
查看>>
loadrunner controller:设置多个load generator
查看>>
关于self.用法的一些总结
查看>>
[原创.数据可视化系列之十三]idw反距离权重插值算法的javascript代码实现
查看>>
SharpDX初学者教程第2部分:创建窗口
查看>>
基于.net standard 的动态编译实现
查看>>
mssql sqlserver in 关键字在值为null的应用举例
查看>>
ArcGIS JS 学习笔记3 实现百度风格的BubblePopup
查看>>
C#中动态加载和卸载DLL
查看>>
在VS2013中使用水晶报表
查看>>
spring的Bean的生命周期
查看>>
ASP.NET 学习.
查看>>