tableView's Skills


iOS 列表性能优化之异步绘制

Demo:stkusegithub/AsyncDraw






Cell不变色、不可选

[A].Cell不变色
(a). Cell不能变色:
 cell.selectionStyle = UITableViewCellSelectionStyleNone;
 //不能变色  (选中的风格:无颜色)

Cell的其他选中色:
//蓝色
cell.selectionStyle = UITableViewCellSelectionStyleBlue; 

//灰色  
cell.selectionStyle = UITableViewCellSelectionStyleGray; 


(b). Cell取消选中,变原色:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //取消选中后,变为原色
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}





[B].Cell不可选
a. 处理tableView的“select”方法:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{
     return nil; //tableview不可选
}


b. 不经过tableView的“select”方法
self.myTableView.allowsSelection = NO;//不响应select
cell.selectionStyle = UITableViewCellSelectionStyleNone;//选中:无色




header标题

[ 1 ].系统自带的方法:titleForHeaderInSection (背景色:深灰

// 深灰色(背景色)
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    ClassesListCellModel * model = self.dataArray[section];
    return model.date;
}



[ 2 ].自己把headerView视图,设置为一个Label

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView * view = [[UIView alloc] init];

    UILabel * date_LB = [[UILabel alloc] init];
    CategoryListCellModel * model = self.dataArray[section];
    date_LB.text = model.date; //格式:@"2017-08-02"
    date_LB.textColor = [UIColor lightGrayColor];
    [view addSubview: date_LB];
    [date_LB mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(view).with.offset(10.f);
        make.centerY.equalTo(view).with.offset(0.f);
   
    }];

    view.backgroundColor = All_BG_Color;
    return view;
}




内容重复:cell复用问题

QuesListTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {
    cell = [[QuesListTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}

使用“Debug View Hierarchy”,查看视图关系

Debug View Hierarchy



解决

cell的复用,定位每一行[tableView cellForRowAtIndexPath:indexPath];

QuesListTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];//定位到每一行
if (!cell) {
    cell = [[QuesListTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}

改善后效果









分割线隐藏:separator

  • 设置separator背景色:透明
    self.quesListTabV.separatorColor = [UIColor clearColor];


  • 设置cell相对于contentView上左下右间距
    在“-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { }”里:

    cell.separatorInset = UIEdgeInsetsMake(0, cell.contentView.frame.size.width/2.f, cell.contentView.frame.size.width/2.f, 0);
    




提前 注册Cell (“register”方法)

  • - (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);

    在创建UITableView的时候,就可以顺带注册复用的Cell!!

    [self.tableView registerClass:[FKTableViewCell class] forCellReuseIdentifier:@"FKCell"];
    

    这样,在“- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { }”里,就只需要:

    FKTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FKCell" forIndexPath:indexPath];
    


    可以省去如下代码:

    static NSString *CellIdentifier = @"FKCell";
    FKTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
    if (cell == nil) {
        cell = [[FKTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        //设置cell
    
    }
    



  • 如果已经用NIB制作了一个Cell:

    - (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);

    注册复用的cell!!

    [self.resourceTabV registerNib:[UINib nibWithNibName:@"ResourceTableViewCell" bundle:nil] forCellReuseIdentifier:@"cell"];
    

    在“- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { }”里:

    ResourceTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    


    可以省去如下代码:

    ResourceTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (!cell) {
       cell = [ResourceTableViewCell xibTableViewCell];
    }
    


    在“ResourceTableViewCell.m”里面:
    //实现类方法
     +(instancetype)xibTableViewCell {
        //在类方法中加载xib文件    firstObject、lastObject都可以
        return [[[NSBundle mainBundle] loadNibNamed:@"ResourceTableViewCell" owner:nil options:nil] lastObject];
    }
    






Xib关联的UITableViewCell


视图布局(Xib文件)

在“JobsTableViewCell.m”里面: (loadNibNamed:加载nib)

//实现类方法
+(instancetype)xibTableViewCell {
    //在类方法中加载xib文件   (仅一个元素 :firstObject、lastObject都可以)

    return [[[NSBundle mainBundle] loadNibNamed:@"JobsTableViewCell" owner:nil options:nil] lastObject];
    //loadNibNamed:关联的名字(本身名字)
}



- (void)awakeFromNib {
    [super awakeFromNib];

    /** 设置控件属性 */
    self.titleImgV.image = [UIImage imageNamed:@"hg_job_avatar"];
    self.titleLB.text = @"工作标题";
    self.detailInfoLB.text = @"工作安排";
    self.littlePicImgV.image = [UIImage imageNamed:@"hg_progress"];
}


使用Cell:
    • 在“-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { }”里:

      JobsTableViewCell * jobDataCell = [tableView dequeueReusableCellWithIdentifier:@"jobCell"];
      //如果缓存池中没有,那么创建一个新的cell
      if (! jobDateCell) {
           //这里换成自己定义的cell,并调用类方法加载xib文件
           jobDataCell = [JobsTableViewCell xibTableViewCell];
      }
      

    不能使用:“alloc”方法创建Cell (❌❌❌❌❌❌❌)
    JobsTableViewCell * jobDataCell = [[JobsTableViewCell alloc]  initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"jobCell"];
    //❌❌❌ 不能使用 “alloc”方法 创建 ❌❌❌
    



    • 另一种使用方式:(注册 复用Cell)
      在创建tableView时,直接注册 复用Cell

      [self.jobListTabV registerNib:[UINib nibWithNibName:@"JobsTableViewCell" bundle:nil] forCellReuseIdentifier:@"jobCell"];
      


      在“-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { }”里的写法:

      JobsTableViewCell * jobDataCell = [tableView dequeueReusableCellWithIdentifier:@"jobCell" forIndexPath:indexPath];
      




自定义的Cell尺寸调整 (setFrame

- (void)setFrame:(CGRect)frame {
    //上 分隔线的距离:SCREEN_WIDTH*30.f/750.f
    frame.origin.y += SCREEN_WIDTH*30.f/750.f;
    //下 分隔线的距离:0 (= size.hight偏差 - origin.y偏差)
    frame.size.height -= SCREEN_WIDTH*30.f/750.f;

    float distance_X = SCREEN_WIDTH*30.f/750.f;//左、右边间距
    frame.origin.x += distance_X;
    frame.size.width -= 2*distance_X;

    [super setFrame:frame];
}


效果:给layer层,加上边框!








添加 长按手势

// 添加长按手势
UILongPressGestureRecognizer * longPressGr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressMyTableView:)];
longPressGr.minimumPressDuration = 1.5f; //长按手势的“最短时长”
[self.myTabV addGestureRecognizer:longPressGr];

//长按手势 的响应方法
-(void)longPressMyTableView:(UILongPressGestureRecognizer *)gesture {
    if(gesture.state == UIGestureRecognizerStateBegan) { //“手势开始”状态
        CGPoint point = [gesture locationInView: self.myTabV];
        NSIndexPath * indexPath = [self.myTabV indexPathForRowAtPoint:point];
    
        if(indexPath == nil) return; //其他 不是Cell所在的地方

    
        NSLog(@"longPress  indexPath.row:%ld",indexPath.row);//所点击cell的位置
        //根据 所点击Cell的位置,做响应操作!
        //add your code here

    }
}







tableView相对于导航栏的偏移

宏定义:
//忽略导航栏
#define SCREEN_WithOutNavBar CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64.f)

定义tableView:

self.detailsListTabV = [[UITableView alloc] initWithFrame:SCREEN_WithOutNavBar style:UITableViewStylePlain];
self.detailsListTabV.separatorColor = [UIColor clearColor];

[self.view addSubview:self.detailsListTabV];


故障的效果:


原因

视图控制器会根据状态栏导航栏标签栏,来调整它所包含的scrollview偏移量!!
由于tableviewcollectionviewtextview等都是继承于scrollview,所以都会出现这种情况。

解决

self.edgesForExtendedLayout = UIRectEdgeNone;//从导航栏开始
//self.extendedLayoutIncludesOpaqueBars = NO;

从导航栏开始,进行tableView的布局!!


效果







Cell里的按钮响应

自定义的ResourceTableViewCell:
  • ResourceTableViewCell.xib

  • ResourceTableViewCell.h”里:

    #import <UIKit/UIKit.h>
    
    @protocol ClickCellDelegate <NSObject> //协议 各按钮点击响应
    - (void)didClickIndexWithBtn:(UIButton *)button;
    @end
    
    
    @interface ResourceTableViewCell : UITableViewCell
    
    @property (nonatomic,weak) id<ClickCellDelegate> delegate;//响应的协议 
    
    /** ⭐️⭐️⭐️直接拖的各个按钮⭐️⭐️⭐️ */
    @property (weak, nonatomic) IBOutlet UIButton *collectionBtn;//收藏按钮
    @property (weak, nonatomic) IBOutlet UIButton *sendToEmailBtn;//传到邮件按钮
    @property (weak, nonatomic) IBOutlet UIButton *previewBtn;//预览按钮
    
    +(instancetype)xibTableViewCell;//初始化方法
    @end
    

  • ResourceTableViewCell.m”里:

    #import "ResourceTableViewCell.h"
    
    #define Button_Tag 1000
    
    
    
    @implementation ResourceTableViewCell
    
    //实现类方法
    +(instancetype)xibTableViewCell {
        //在类方法中加载xib文件    firstObject、lastObject都可以
        return [[[NSBundle mainBundle] loadNibNamed:@"ResourceTableViewCell" owner:nil options:nil] lastObject];
    }
    
    
    - (void)awakeFromNib {
        [super awakeFromNib];
    
    
        _collectionBtn.tag = Button_Tag;        //收藏按钮
        _sendToEmailBtn.tag = Button_Tag + 1;   //发送按钮
        _previewBtn.tag = Button_Tag + 2;       //阅览按钮
    }
    
    
    /** ⭐️⭐️⭐️各按钮直接拖的方法⭐️⭐️⭐️ */
    - (IBAction)collectBtnPress:(id)sender {
        [self tapWithBtn:sender];
    }
    - (IBAction)sendToEmailBtnPress:(id)sender {
        [self tapWithBtn:sender];
    }
    - (IBAction)perviewBtnPress:(id)sender {
        [self tapWithBtn:sender];
    }
    
    -(void)tapWithBtn:(UIButton *)button {
        //声明好的代理
        if([self.delegate respondsToSelector:@selector(didClickIndexWithBtn:)]) {
            [self.delegate didClickIndexWithBtn:button];
        }
    }
    
    @end
    


使用

在使用了“ResourceTableViewCell”的tableView所在界面里:

  • 满足协议<ClickCellDelegate>

  • 设置全局变量:用来获取 响应Cell 所在位置!!
    NSIndexPath * _whole_IndexPath; //全局选择项

  • 注册Cell:(在创建tableView时)
    [self.reourcesTabV registerNib:[UINib nibWithNibName:@"ResourceTableViewCell" bundle:nil] forCellReuseIdentifier:@"cell"];


  • 设置Cell的代理<ClickCellDelegate>

    在“-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { }”里面:

    ResourceTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    cell.delegate = self;//设置代理
    


  • 重写代理方法

    #pragma mark - ClickCellDelegate
    -(void)didClickIndexWithBtn:(UIButton *)button {
    
      ResourceTableViewCell *cell = (ResourceTableViewCell *)[[[button superview] superview] superview];
      //cell、xib、view 三层
      / ** 解释:
        第1层:[button superview]是ResourceTableViewCell的“contentView”;
        第2层:第二个superview是ResourceTableViewCell⭐️自己本身⭐️的“cell”;
        第3层:第三个superview是⭐️UITableView⭐️的“cell”。
      * /
    
    
      _whole_IndexPath = [self.reourcesTabV indexPathForCell:cell];
      //⭐️⭐️⭐️获取到是哪一行的Cell  被点击!⭐️⭐️⭐️
      //NSLog(@"indexPath row is = %li",(long)_whole_IndexPath.row);
    
    
      //获取该行Cell的模型
      ResourceListCellModel * model = self.dataArray[_whole_IndexPath.row]; //获取该行Cell的模型
    
      //⭐️⭐️⭐️用Cell按钮的tag值,来判断是哪个按钮⭐️⭐️⭐️
      switch (button.tag - 1000) { 
          case 0:{ //收藏
    
          }break;
          case 1:{ //发送邮件
    
          }break;
          case 2:{ //预览
    
          }break;
          default:
              break;
    
    }
    


思路
1.获取点击的Cell所在位置(indexPath);
2.根据tag值,判断是哪个按钮(子视图)被点击

















goyohol's essay

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267