UITableView总结

来源:互联网 发布:面纱3.0雾化器做芯数据 编辑:程序博客网 时间:2024/05/16 14:51

1.协议介绍
UITableViewDataSource
UITableViewDelegate(常用)
2.刷新
下拉刷新:
上拉刷新
3.搜索
4.重用
自定义cell
不使用重用方法
注册Cell
5.编辑
滑动更多
6.优化
UITableView 总结

UITableView是UIScrollView的子类,因此它可以自动响应滚动事件(一般为上下滚动)。
它内部包含0到多个UITableViewCell对象,每个table cell展示各自的内容。当新cell需要被显示时,就会调用tableView:cellForRowAtIndexPath:方法来获取或创建一个cell;而不可视时,它又会被释放。由此可见,同一时间其实只需要存在一屏幕的cell对象即可,不需要为每一行创建一个cell。

1.协议介绍
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

2.刷新
下拉刷新:

第三方: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 为成员变量,只需要增加猝发时间就可以了

上拉刷新

1.第三方:EGORefreshTableFooterView

2.自加按钮:

- (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.视图滚到最后直接加载更多:
    - (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协议       #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;            }        }

不用xib的话,可以直接添加代码

        _bSearchBar = [[UISearchBar alloc] init];        _bSearchBar.delegate = self;        [_bSearchBar setPlaceholder:@"搜索"];        CGSize size =  [_bSearchBar sizeThatFits:_tableView.bounds.size];        _bSearchBar.frame = CGRectMake(0, 0, size.width, size.height);        _tableView.tableHeaderView = _byxSearchBar;        _bSearchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:_bSearchBar contentsController:self];        _bSearchDisplayController.searchResultsDataSource = self;        _bSearchDisplayController.searchResultsDelegate = self;        _bSearchDisplayController.delegate = self;        _bSearchDisplayController.searchResultsTitle = @"";        _bSearchDisplayController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;

4.cell重用

        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

  1. 新建cell文件,继承UITableViewCell

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

               static NSString *cellid = @"cellIdentifier";        TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellid];        if (!cell) {            cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellid];        }        3. 如果有xib        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中获取到想要的一个)

               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: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

        - (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出来。

5.编辑

        //是否可编辑        - (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(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];        }

6.优化

    1.最好改造原生的tableViewCell,尽量不要用xib自定制cell,可以尽量在drawRect中绘制    2.尽量使用重用机制,不要创建太多cell    3.尽量不要使用透明视图,和layer改造    4.重载共同部分可以放在生成Cell部分    5.尽量不要老调用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);/*
0 0
原创粉丝点击