美文网首页
tableView总结

tableView总结

作者: 上玄月_lxl | 来源:发表于2018-06-26 01:17 被阅读0次

    本文旨在帮助各位大佬复习巩固基础知识。

    一、tableView类型与系统自带cell类型
    二、两种注册系统cell的方法
    三、常用代理方法总结
    四、实战练习
    五、巩固提高-两个tableView的联动
    六、感谢参考文章 与本文demo链接

    一、tableView类型与系统自带cell类型

    1、tableView样式可分为普通样式与分区样式两种:

    UITableViewStylePlain、UITableViewStyleGrouped

    两者的区别在于一个grouped样式可以有分区头,而plain样式则没有

    2、cell样式可分为以下四种:

    UITableViewCellStyleValue1、UITableViewCellStyleValue2、UITableViewCellStyleDefault、UITableViewCellStyleSubtitle

    四种cell样式的区别在于imageView、textLabel、detailTextLabel、accessoryType 的位置、显示不同。

    如图:


    552b2419-655b-4639-b454-e4f11bd0bb82.gif

    二、两种注册系统cell的方法

    cell注册目的都在于cell的复用来节省开支。

    1、常用的,在代理行为返回cell时进行注册(据了解:系统推荐用这个方法,这个方法在某些情况下更加能避免循环复用)

    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
        // kPlaceHolderCellId是我定义的一个宏字符串
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kPlaceHolderCellId];
    
        if (!cell) {
    
            cell = [[UITableViewCell alloc]initWithStyle:(UITableViewCellStyleValue1) reuseIdentifier:kPlaceHolderCellId];
    
        }
    
        return cell;
    
    }
    
    

    2、在tableView申请之后进行注册(这样在cellForRowAtIndexPath里就不需要对cell 是否为空进行判断)

    
     [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kPlaceHolderCellId];
    
    // 下面是代理方法,
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kPlaceHolderCellId];
    
        return cell;
    
    } 
    
    

    本文不对xib注册进行解释,详情可查看其他朋友文章。

    三、常用代理方法总结

    1、数据源:

    
    // 返回第section组中有多少行 
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; 
    
    // 返回多少组,没实现该方法,默认为1 
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
    
    

    2、UITableViewDelegate代理方法

    
    
    // 即将显示tableviewcell时调用
    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
    
    // 即将显示header时调用,在cell之后调用
    - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
    
    // 即将显示footer时调用,在header之后调用
    - (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
    
    // 在删除cell之后调用,停止显示cell的时候调用,界面不显示cell时。
    - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath NS_AVAILABLE_IOS(6_0);
    
    // 停止显示header的时候调用
    - (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
    
    // 停止显示footer的时候调用
    - (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0)
    

    3、操作cell时调用的方法

    // cell选中时调用
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
    // cell取消选中时调用
    - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
    

    4、设置分组view的方法

    
    // 返回某个section对应的header标题
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
    
    // 返回某个section对应的footer标题
    
    - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; 
    
    // 设置第section分组的header 
    
    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; 
    
    // 设置第section分组的footer 
    
    - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
    
    

    5、高度的代理方法

    
    // 在设置每行cell的高度,header的高度,footer的高度 
    
    // 设置某行cell高度
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; 
    
    // 设置header高度
    
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section; 
    
    // 设置footer高度 
    
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
    
    

    6、编辑模式相关的代理方法

    // 返回每一行cell的编辑模式, 可以再次设置add或者删除操作。
    - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
    // cell左滑删除时,删除按钮的标题
    - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
    // 自定义编辑左滑后出现的界面。  不止只有一个delete按钮, 可以自行定义,返回一个数组。数组中放着UITableviewRowAction
    - (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0);
    // 未实现 默认为yes,进入编辑时,cell是否缩进。  在开启编辑状态时调用。
    - (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;
    
    // 右滑准备进行编辑的时候 调用。 将setediting = yes时不调用
    - (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
    // 完成编辑的时候调用
    - (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;
    

    7、索引

    
    //返回要显示的section索引标题
    
    - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; 
    
    // return list of section titles to display in section index view (e.g. "ABCD...Z#") 
    
    // 点击右侧索引表项时调用
    
    - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; 
    
    // 返回指定点所在位置的indexPath 
    
    - (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point; 
    
    // 返回指定cell所在的indexPath
    
    - (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell;
    
    // 返回指定范围rect中的所有cell的indexPath
    
    - (NSArray *)indexPathsForRowsInRect:(CGRect)rect;
    
      // returns nil if rect not valid
    
    // 返回索引indexPath所指向的cell。
    
    - (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath;
    
    

    8、tableview的滚动方法

    
    // 根据传入的indexPath,滚动到相对应的位置,第二个参数是控制对应的cell再滚动后处于tableview的顶部/底部/中部等 
    
    - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
    
    // 滚动到被选中项。 滚动后处于tableview的顶部/底部/中部等
    
    - (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
    
    

    9、插入,删除,刷新,移动section组

    
    // 插入,删除,刷新,移动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 NS_AVAILABLE_IOS(3_0); 
    
    // 移动section 
    
    - (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection NS_AVAILABLE_IOS(5_0);
    
    

    四、实战练习

    1、自定义cell

    效果图:

    自定义cell.gif

    1)、通过自定义cell可以实现各式各样的我们想要的样式,当cell定义后,如果我们暴露在外面的是label,则可以通过改变label的text属性来进行赋值,如果暴露到外面的是string,想通过string赋值来改变label的话,我使用的是rac进行监听string的变化。

    2)、cell的定义可以通过高内聚来实现数据与controller的分离。

    
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
        UITableViewCell *cell;
    
        if (indexPath.row%2 == 0) {
    
            // 通过cell的事件方法处理,将cell的定义在cell定义中进行自己的实现,这样就可以达到高内聚低耦合。 下面的model是定义的一种数据类型,这样congtroller也不需要管具体数据是什么了
    
            OneTableViewCell *oneCell = [OneTableViewCell createCellWithTableView:tableView];
    
            oneCell.myModel = _model;
    
            cell = oneCell;
    
        }else{
    
            // 通过传字符串处理,这个cell暴露在外面的string。我在cell实现中进行了rac监听
    
            TwoTableViewCell *oneCell = [tableView dequeueReusableCellWithIdentifier:kPlaceHolderCellId2];
    
            if (oneCell == nil) {
    
                oneCell = [[TwoTableViewCell alloc]initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:kPlaceHolderCellId2];
    
            }
    
            oneCell.nameStr = _nameArr[indexPath.row];
    
            oneCell.messageStr = _messageArr[indexPath.row];
    
            cell = oneCell;
    
        }
    
        return cell;
    
    }
    
    

    第一个cell

    
    // 类方法用来作为cell对外的调用接口
    
    +(instancetype)createCellWithTableView:(UITableView *)tableView{
    
        OneTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kPlaceHolderCellId];
    
        if (cell == nil) {
    
            cell = [[OneTableViewCell alloc]initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:kPlaceHolderCellId];
    
        }
    
        return cell;
    
    }
    
    // 实现cell布局
    
    -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    
        if (self) {
    
            id headerView = ImageView.img(@"header2.jpg").borderRadius(40);
    
            _nameLabel = Label.fitSize.str(_myModel.name);
    
            _messageLabel = Label.fitSize.str(_myModel.message);
    
            id messageView = View;
    
            id verS1 = VerStack(@5,
    
                     _nameLabel,
    
                     _messageLabel,).gap(5).embedIn(messageView);
    
            id verS2 = VerStack(@5,
    
                                headerView,
    
                                @5);
    
            HorStack(@5,verS2,verS1,NERSpring).gap(15).embedIn(self);
    
        }
    
        return self;
    
    }
    
    // model赋值
    
    -(void)setMyModel:(YSCellModel *)myModel{
    
        _myModel = myModel;
    
        self.nameLabel.text = _myModel.name;
    
        self.messageLabel.text = _myModel.message;
    
        NSLog(@"执行了,%@",_myModel.name);
    
    }
    
    

    第二个cell

    
    -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    
        if (self) {
    
            id headerView = ImageView.img(@"header4.jpg").borderRadius(40);
    
            UILabel *nameLabel = Label.fitSize.str(_nameStr);
    
            UILabel *speakLabel = Label.fitSize.str(_messageStr);
    
            id messageView = View;
    
            id verS1 = VerStack(@5,
    
                                nameLabel,
    
                                speakLabel,).gap(5).embedIn(messageView);
    
            id verS2 = VerStack(@5,
    
                                headerView,
    
                                @5);
    
            HorStack(@5,verS2,verS1,NERSpring).gap(15).embedIn(self);
    
            // 通过rac监听string的改变来改变label的text
    
            [RACObserve(self, self.nameStr) subscribeNext:^(id  _Nullable x) {
    
                nameLabel.text = x;
    
            }];
    
            [RACObserve(self, messageStr) subscribeNext:^(id  _Nullable x) {
    
                speakLabel.text = x;
    
            }];
    
        }
    
        return self;
    
    }
    
    

    2、cell的侧滑按钮-cell的移动与编辑状态

    效果图:

    侧滑多按钮.gif

    1)、cell的侧滑按钮可通过editActionsForRowAtIndexPath行为返回的数组来进行定义。

    2)、cell的移动需要在编辑状态下实现canMoveRowAtIndexPath 和 moveRowAtIndexPath两个方法。

    cell的侧滑实现

    
    // 自定义编辑左滑后出现的界面。  不止只有一个delete按钮, 可以自行定义,返回一个数组。数组中放着UITableviewRowAction
    
    -(NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
    
        UITableViewRowAction *action0 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"关注" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
    
            NSLog(@"点击了关注");
    
            // 收回左滑出现的按钮(退出编辑模式)
    
            tableView.editing = NO;
    
        }];
    
        UITableViewRowAction *action1 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
    
            [self.myArray removeObjectAtIndex:indexPath.row];
    
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    
        }];
    
        return @[action1, action0];
    
    }
    
    

    cell的编辑状态下的移动

    
    // 在编辑状态下可以移动
    
    -(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{
    
        return YES;
    
    }
    
    -(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
    
        // demo中并没有在这里操作,如果你不想退出程序后变回原样的话,就在这里对你的数据数组进行换位置
    
    }
    
    

    cell编辑的样式

    
    // 返回cell支持的编辑样式   可以自己尝试查看每种样式的样子
    
    - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    
        //表示支持默认操作
    
        //return UITableViewCellEditingStyleNone;
    
        //表示支持删除操作
    
    //    return UITableViewCellEditingStyleDelete;
    
        //表示支持新增操作
    
    //    return UITableViewCellEditingStyleInsert;
    
        return UITableViewCellEditingStyleDelete ;
    
    }
    
    

    3、mjrefresh的刷新

    关于这个第三方库的使用,网上有蛮多教程的。这里只介绍一个切换图片的类似动图的刷新状态。

    效果图(gif有点卡):

    mjrefsh刷新.gif

    代码

    
        MJRefreshGifHeader *header = [MJRefreshGifHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
    
        NSArray *test = [NSArray arrayWithObjects:Img(@"header4.jpg"),Img(@"header2.jpg"), nil];
    
    // 注意,只有隐藏了下面两个状态栏才能让图片在居中显示。如果你还希望自定义文字可查看demo,也可自己上网八一八更详细的资料 
    
        // 隐藏时间
    
        header.lastUpdatedTimeLabel.hidden = YES;
    
        // 隐藏状态栏
    
        header.stateLabel.hidden = YES;
    
    

    4、多分区的删除cell - 索引

    效果图:

    1)、之所以单独拿出来讲是因为我这种菜鸡之前也不会,删除时候总是崩溃,所以总结了两种方法来删除多分区的cell。(demo中没有对一个分区中只有一个cell的情况进行适配)

    2)、索引需要实现sectionIndexTitlesForTableView 和 sectionForSectionIndexTitle两个方法就可以了

    删除cell

    
    // Override to support editing the table view.
    
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    
            // 首先获取对应分区的数组 然后删除数组中你删除的cell
    
            NSString *str = self.allKeys[indexPath.section];
    
            self.dataArray = [self.dictionary objectForKey:str];
    
            [self.dataArray removeObjectAtIndex:indexPath.row];
    
            if (self.dataArray.count == 0) {
    
                [self.dictionary removeObjectForKey:str];
    
                self.allKeys = [self.dictionary allKeys];
    
            }
    
            // 这样重新加载不能带动画的删除  这就是方法1
    
    //        [self.tableView reloadData];
    
            // 这样可以带动画的删除cell   这样就是方法2
    
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:(UITableViewRowAnimationFade)];
    
    }
    
    

    索引

    
    //返回索引数组
    
    -(NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView{
    
        return [self.allKeys sortedArrayUsingSelector:@selector(compare:)];
    
    }
    
    //响应点击索引时的委托方法
    
    -(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index{
    
        NSInteger count = 0;
    
        for (NSString *character in self.allKeys) {
    
            if ([[character uppercaseString] hasPrefix:title]) {
    
                return count;
    
            }
    
            count++;
    
        }
    
        return  0;
    
    }
    
    

    五、巩固提高-两个tableView的联动

    tableview的联动有两种方式,有人说使用willDisplayHeaderView 和 didEndDisplayingHeaderView 方法会出现联动不准确的bug,也许我神经比价大条并没有感觉会有不准确的情况,不过第二种方法代码量确实较少。仁者见仁。以下为两种方法的实现方式

    方法一

    
    // 此处省略leftTable 和 rightTable的声明  和  数据的声明过程,详细代码稍后会发demo出来
    
    #pragma mark 方法一
    
    // 点击左侧可滚动右侧
    
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
        if (tableView == _leftTabele) {
    
            NSInteger select = indexPath.row;
    
            [_rightTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:select] atScrollPosition:UITableViewScrollPositionTop animated:YES];
    
        }
    
    }
    
    // 标记右侧tableVIew是向下滚动还是向上滚动
    
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    
        if (scrollView == self.leftTabele) return;
    
        static CGFloat lastOffsetY = 0;
    
        UITableView *tableview = (UITableView *)scrollView;
    
        if (tableview == _rightTable) {
    
            _isScrollDown = lastOffsetY < scrollView.contentOffset.y; // 手指向上拖动就为真,向下拖动就为假(界面向上滚动、界面向下滚动)
    
            lastOffsetY = scrollView.contentOffset.y; // 记录当前y值,向下变大,向上变小
    
    //        NSLog(@"%@",_isScrollDown ? @"1":@"2");
    
        }
    
    }
    
    // 即将展示头部标题  手指向下拖动的时候才显示这个
    
    -(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section{
    
        // 当前tableView 是右侧的, 滑动方向向下,是用户拖拽产生的滚动
    
        if ((tableView ==  _rightTable) && !_isScrollDown && _rightTable.dragging) {
    
            NSLog(@"分区将要显示:%ld",section);
    
            [self selectRowAtIndexPath:section];
    
        }
    
    }
    
    // 分区标题展示结束 手指向上滑动的时候显示这个
    
    -(void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section{
    
        // 当钱tableView 是右侧的,滚动方向是向上,是用户拖拽产生的滚动
    
        NSLog(@"t2:%d",_rightTable.dragging);
    
        if ((tableView == _rightTable) && _isScrollDown && _rightTable.dragging) {
    
            NSLog(@"分区将要隐藏:%ld",section);
    
            [self selectRowAtIndexPath:section];
    
        }
    
    }
    
    // 当拖动右边 tableView的时候,处理左边tableView
    
    -(void)selectRowAtIndexPath:(NSInteger)index{
    
        [_leftTabele selectRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] animated:YES scrollPosition:(UITableViewScrollPositionTop)];
    
    }
    
    

    方法二

    #pragma mark 方法二
    // 此处省略leftTable 和 rightTable的声明  和  数据的声明过程,详细代码稍后会发demo出来
    
    // 点击左侧可滚动右侧
    
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
        if (tableView == _leftTabele) {
    
            NSInteger select = indexPath.row;
    
            [_rightTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:select] atScrollPosition:UITableViewScrollPositionTop animated:YES];
    
        }
    
    }
    
    // 标记右侧tableVIew是向下滚动还是向上滚动
    
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    
        if (scrollView == self.leftTabele) return;
    
        NSLog(@"这里是视图上所有cell:%@",[self.rightTable indexPathsForVisibleRows]);
    
        NSLog(@"这里是最考上的一个cell:%@",[[self.rightTable indexPathsForVisibleRows] firstObject]);
    
        // 取出显示在 视图 且最靠上 的 cell 的 indexPath
    
        NSIndexPath *topHeaderViewIndexpath = [[self.rightTable indexPathsForVisibleRows] firstObject];
    
        // 左侧 talbelView 移动到的位置 indexPath
    
        NSIndexPath *moveToIndexpath = [NSIndexPath indexPathForRow:topHeaderViewIndexpath.section inSection:0];
    
        // 移动 左侧 tableView 到 指定 indexPath 居中显示
    
        [self.leftTabele selectRowAtIndexPath:moveToIndexpath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
    
    }
    
    

    方法二解析图(图片来源于网络)

    tableView联动解析.png

    我遇到的bug

    如图:

    bug版联动.gif

    bug描述:图片要展示的bug是,当滑动右侧tableView 的时候会直接从A分区跳到N分区,无论上拉还是下拉。后来解决这个bug,是因为我用的MAC外接了一个显示器,当使用快捷键ctrol+option进行快速屏幕拖动时出发了模拟器的option选项,从而导致了这个bug。解决办法就是在模拟器上再点击的时候再按住option就可以了。

    鸣谢文章链接

    iOS tableView详解

    iOS两个 TableView 联动. 思路简单明了,无bug!

    本文demo链接

    相关文章

      网友评论

          本文标题:tableView总结

          本文链接:https://www.haomeiwen.com/subject/kpouyftx.html