zoukankan      html  css  js  c++  java
  • UITableView总结

    1.协议介绍
    UITableViewDataSource(11)
    UITableViewDelegate(常用)
    2.刷新
    下拉刷新:
    上拉刷新
    3.搜索
    4.重用
    自定义cell
    不使用重用方法
    注册Cell
    5.编辑
    滑动更多
    6.优化
    UITableView 总结
    
    
    
    UITableView是UIScrollView的子类,因此它可以自动响应滚动事件(一般为上下滚动)。
    它内部包含0到多个UITableViewCell对象,每个table cell展示各自的内容。当新cell需要被显示时,就会调用tableView:cellForRowAtIndexPath:方法来获取或创建一个cell;而不可视时,它又会被释放。由此可见,同一时间其实只需要存在一屏幕的cell对象即可,不需要为每一行创建一个cell。 
    
    1.协议介绍
    UITableViewDataSource(11
    //每个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;
    
    ?
    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.自加按钮:
    
    
    - (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;
        }
    }
    demo: https://github.com/Jonear/iosDemo/tree/master/TableViewFresh
    
    4.重用
    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,跟普通写法一样
    
    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
    
    tic 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
    
    
    // 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.编辑
    
    //是否可编辑
    - (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];
         
    }
       demo:http://code4app.com/ios/SWTableViewCell/5269d9376803fa5367000001
    
    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);
  • 相关阅读:
    C/C++字符串函数之复制函数
    tesseract api C++使用例子
    error C2275: “XXX”: 将此类型用作表达式非法
    Socket通信原理探讨(C++为例)
    模拟按键,点击,滑动,在光标处输出字符
    安卓使用Root权限实现后台模拟全局按键、触屏事件方法(类似按键精灵)
    【 转】__try,__except,__finally,__leave异常模型机制
    提高VS2010运行速度的技巧
    解决VS2010子目录中的.cpp文件引用上一级目录的stdafx.h找不到定义的问题
    1009MySQL数据库InnoDB存储引擎Log漫游
  • 原文地址:https://www.cnblogs.com/keyan1102/p/4744147.html
Copyright © 2011-2022 走看看