美文网首页UIview子类
UITableViewCell总结

UITableViewCell总结

作者: ___1o_8o | 来源:发表于2016-01-11 17:15 被阅读407次

    // 注意:
    1. 通过xib来创建UITableViewCell需要在xib的identity上写上重用标识

     2. 通过storyboard来创建UITableViewCell需要在storyboard的identity上写上重用标识
    
     3.  有时候每一行的cell用的不一定是同一种UITableVIewCell,对象池中也会有不同的UITableViewCell等待重用,那么在重用的时候可能得到的是错误的UITableViewCell}
         解决方法:可以通过重用属性reuseIdentifier来对应不同的UITableViewCell
    
     4. 往cell添加子控件的时候,把子控件添加到contentView上面
    
     5. 不应该在initWithStyle中设置子控件的Frame,因为父控件的Frame还没有确定,子控件设置Frame不太好,我们应该在layoutSubviews中设置Frame
     layoutSubviews (一定要调用父类) :
        当一个控件的frame发生改变的时候调用,Frame前后要不一致
        将一个控件添加到当前控件的时候调用
    

    一、UITableViewCell重用的封装

    + (instancetype)HeroCell:(UITableView *)tableView;{
        HeroTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ID"];
        if (!cell) {
            cell = [[HeroTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"ID"];
        }
        return cell;
    }
    

    二、UITableViewCell的封装 - 系统自定义

    #import <UIKit/UIKit.h>
    @class Hero;
    @interface HeroTableViewCell : UITableViewCell
    + (instancetype)HeroCell;
    @property (nonatomic, strong) Hero *hero;
    @end
    
    #import "HeroTableViewCell.h"
    #import "Hero.h"
    @implementation HeroTableViewCell
    + (instancetype)HeroCell{
        HeroTableViewCell *cell = [[HeroTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
        return cell;
    }
    
    - (void)setHero:(Hero *)hero{
        _hero = hero;
        self.imageView.image = [UIImage imageNamed:hero.icon];
        self.textLabel.text = hero.name;
        self.detailTextLabel.text = hero.intro;
    }
    @end
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        Hero *hero = self.heros[indexPath.row];
        HeroTableViewCell *cell = [HeroTableViewCell HeroCell];
        cell.hero = hero;
        return cell;
    }
    

    三、UITableViewCell的封装 - 动态单元格
    1.动态单元格得使用UITableViewController

    2.UITableViewController的动态单元格cell要写自定义的UITableViewCell,从而通过UITableViewCell实现自定义

    3.UITableViewCell -> AppViewCell的代码实现

    #import <UIKit/UIKit.h>
    @class App;
    @class AppViewCell;
    /// 代理
    @protocol AppViewCellDelegate <NSObject>
    @optional
    - (void)downloadBtnDidClick:(AppViewCell *)appViewCell;
    @end
    
    @interface AppViewCell : UITableViewCell
    + (instancetype) appViewCell:(UITableView *)tableView;
    @property (nonatomic, strong) App *app;
    /// 代理属性
    @property (nonatomic, assign) id<AppViewCellDelegate> delegate;
    @end
    
    #import "AppViewCell.h"
    #import "App.h"
    
    @interface AppViewCell ()
    /// 属性连线
    @property (weak, nonatomic) IBOutlet UIImageView *iconView;
    @property (weak, nonatomic) IBOutlet UILabel *nameView;
    @property (weak, nonatomic) IBOutlet UILabel *detailView;
    @property (weak, nonatomic) IBOutlet UIButton *downloadBtn;
    @end
    
    @implementation AppViewCell
    - (IBAction)downloadBtnDidClick {
        /// 禁用下载按钮
        self.downloadBtn.enabled = NO;
        /// 设置已下载
        self.app.isDownloaded = YES;
        /// 判断代理是否实现了代理方法
        if ([self.delegate respondsToSelector:@selector(downloadBtnDidClick:)]) {
            [self.delegate downloadBtnDidClick:self];
        }
    }
    
    + (instancetype)appViewCell:(UITableView *)tableView{
        //dequeueReusableCellWithIdentifier会从缓存中创建Cell,但是如果缓存中没有可重用的cell,则查询系统的cell原型,通过原型创建cell,.没有原型则报错:
        AppViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"app"];
        return cell;
    }
    
    - (void)setApp:(App *)app{
        _app = app;
        self.iconView.image = [UIImage imageNamed:app.icon];
        self.nameView.text = app.name;
        self.detailView.text=[NSString stringWithFormat:@"大小:%@M,下载数量:%@",app.size,app.download];
        self.downloadBtn.enabled = !app.isDownloaded;
    }
    @end
    

    四、UITableViewCell的封装 - xib
    1.xib名和UITableViewCell名一般相同
    2.xib中的控件要进行属性连线
    3.代码实现

    #import <UIKit/UIKit.h>
    @class CZTg;
    
    @interface CZTgCell : UITableViewCell
    //返回当前自定义的cell
    + (instancetype) tgCell:(UITableView *)tableView;
    //为当前自定义cell赋值
    @property (nonatomic,strong) CZTg *tg;
    
    @end
    
    #import "CZTgCell.h"
    #import "CZTg.h"
    
    @interface CZTgCell()
    @property (weak, nonatomic) IBOutlet UIImageView *iconView;
    @property (weak, nonatomic) IBOutlet UILabel *titleView;
    @property (weak, nonatomic) IBOutlet UILabel *priceView;
    @property (weak, nonatomic) IBOutlet UILabel *buyCountView;
    @end
    @implementation CZTgCell
    
    //创建自定义cell
    + (instancetype)tgCell:(UITableView *)tableView
    {
        //1.定义重用标识
        NSString *ID=@"tg";
        //2.从缓存中创建cell
        CZTgCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
        //3.判断是否成功创建出cell,如果没有就自己从Xib中创建
        if (cell==nil) {
            NSLog(@"aaaaaaa");
            cell=[[[NSBundle mainBundle] loadNibNamed:@"CZTgCell" owner:self options:nil] lastObject];
        }
        return  cell;
    }
    
    - (void)setTg:(CZTg *)tg
    {
        _tg=tg;
        self.iconView.image=[UIImage imageNamed:tg.icon];
        self.titleView.text=tg.title;
        self.priceView.text=[NSString stringWithFormat:@"¥%@",tg.price];
        self.buyCountView.text=[NSString stringWithFormat:@"%@人已购买",tg.buyCount];
    }
    @end
    

    五、UITableViewCell的封装 - 纯代码
    1.思路:
    1.1重写UITableViewCell的initWithStyle方法(记得先super父类方法),在方法中新建控件并添加到cell中,再设置控件的属性值
    1.2在-(void)setMessageFrame方法中设置数据
    1.3在-(void)layoutSubviews中设置Frame (layoutSubviews是在子控件添加到父类的时候会调用)
    2.控件的Frame已经在模型中实现了,所以cell就不需要再设置Frame
    3.代码的实现:

    #import <UIKit/UIKit.h>
    @class CZMessageCellFrame;
    
    @interface CZMessageCell : UITableViewCell
    + (instancetype) messageCell:(UITableView *)tableView;
    
    @property (nonatomic,strong) CZMessageCellFrame *messageFrame;
    @end
    
    #import "CZMessageCell.h"
    #import "CZMessage.h"
    #import "CZMessageCellFrame.h"
    
    @interface CZMessageCell ()
    @property (nonatomic,weak) UILabel *timeView;
    @property (nonatomic,weak) UIImageView *iconView;
    @property (nonatomic,weak) UIButton *textView;
    @end
    
    @implementation CZMessageCell
    
    + (instancetype) messageCell:(UITableView *)tableView
    {
        NSString *ID=@"QQ";
        CZMessageCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
        if (cell==nil) {
            //这个方法是父类的方法,也就意味着它只能创建出父类中默认的系统自带的cell.而不能满足我们的需要,所以我们就需要做重写,在调用方法的时候调用我们子类自己重写过后的方法。
            cell=[[CZMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
        }
        return  cell;
    }
    //根据多态,系统会根据类型调用子类重写过后的方法
    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    {
        //1.先初始化父类成员
        self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self) {
            //1.添加timeView
            UILabel *timeView=[[UILabel alloc] init];
            self.timeView=timeView;
            //设置居中
            timeView.textAlignment=NSTextAlignmentCenter;
            timeView.font=[UIFont systemFontOfSize:13];
            timeView.textColor=[UIColor lightGrayColor];
            [self addSubview:timeView];
            //2.添加iconView
            UIImageView *iconView=[[UIImageView alloc] init];
            self.iconView=iconView;
            [self addSubview:iconView];
            //3.添加textView
            UIButton *textView=[[UIButton alloc] init];
            self.textView=textView;
            //设置按钮的文本色
            [textView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            //设置按钮的字体大小
            textView.titleLabel.font=[UIFont systemFontOfSize:14];
            //设置自动换行
            textView.titleLabel.numberOfLines=0;
            //为按钮添加内容的内间距
            textView.contentEdgeInsets=UIEdgeInsetsMake(0, 20, 0, 20);
            //为按钮添加背景色
            //textView.backgroundColor=[UIColor redColor];
            [self addSubview:textView];
        }
        return self;
    }
    
    - (void)setMessageFrame:(CZMessageCellFrame *)messageFrame
    {
        _messageFrame=messageFrame;
        //设置数据
        [self setDatas];
    }
    //设置数据
    - (void) setDatas
    {
        CZMessage *msg=self.messageFrame.message;
    
        self.timeView.text=msg.time;
    
        if (msg.type==MessageTypeMe) {
            self.iconView.image=[UIImage imageNamed:@"me"];
            //根据消息类型设置消息文本的背景图片
            [self.textView setBackgroundImage:[self resizeImageWithName:@"chat_send_nor"] forState:UIControlStateNormal];
            [self.textView setBackgroundImage:[self resizeImageWithName:@"chat_send_press_pic"] forState:UIControlStateHighlighted];
        }
        else
        {
            self.iconView.image=[UIImage imageNamed:@"other"];
            [self.textView setBackgroundImage:[self resizeImageWithName:@"chat_recive_nor"] forState:UIControlStateNormal];
            [self.textView setBackgroundImage:[self resizeImageWithName:@"chat_recive_press_pic"] forState:UIControlStateHighlighted];
        }
        [self.textView setTitle:msg.text forState:UIControlStateNormal];
    
    }
    
    //返回拉伸之后的图片
    - (UIImage *) resizeImageWithName:(NSString *)name
    {
        return [[UIImage imageNamed:name] resizableImageWithCapInsets:UIEdgeInsetsMake(30, 20, 18, 30) resizingMode:UIImageResizingModeStretch];
    }
    
    //当将当前控件添加到父容器的时候,自动调用这个方法,设置它的子控件的Frame
    //如现在这个情况:当创建好cell,添加到tableView中的时候,会调用这个方法设置cell 的三个子控件的frame
    - (void) layoutSubviews
    {
        //判断是否需要显示时间
        self.timeView.hidden=! self.messageFrame.showTime;
        self.timeView.frame=self.messageFrame.timeViewF;
        self.iconView.frame=self.messageFrame.iconViewF;
        self.textView.frame=self.messageFrame.textViewF;
    }
    @end
    

    相关文章

      网友评论

        本文标题:UITableViewCell总结

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