纯代码自定义不等高cell

数据模型、plist解析这里就不过多赘述。

错误思路之一:

    通过在heightForRowAtIndexPath:方法中调用cellForRowAtIndexPath:拿到cell,再拿到cell的子控件的最大Y值的方法是不可取的。会出现死循环,因为cellForRowAtIndexPath:方法中会调用heightForRowAtIndexPath:方法。
错误思路之二:

    在layoutSubviews方法中,根据子控件的高度,计算cell的高度。先初始化一个变量为0为cell的高度,计算出来所有子控件的高度,最后再计算cell的高度。
    思路2.1
    在layoutSubViews中设置cell的高度,不可行,因为会继续调用layoutSubviews,(当cell的frame被修改时候会调用layoutSubViews)
    思路2.2
    再给自定义cell添加一个cellHeight属性,拿到在layoutSubviews中计算的cell的高度。再再heightForRowAtIndexPath:返回行高,也是不可行的,照样死循环(返回cell的高度需要先拿到cell,所以死循环)。
错误思路之三:

    在模型中添加一个行高属性,把layoutSubviews中计算的cell高度赋值给模型的行高属性,在heightForRowAtIndexPath:中通过模型拿到行高,不可行。因为时机不对。事实上,系统会先调用heightForRowAtIndexPath:方法,然后计算出来cell的高度,根据cell的高度调用layoutSubviews方法,布局子控件的位置。

综合思路三:

  要想拿到cell高度,需要在heightForRowAtIndexPath:方法调用之前将所有的子控件的高度计算清楚。
      在heightForRowAtIndexPath:方法中再次计算(空算)子控件的高度,定义局部变量cellHeight,根据子控件的最大Y值,计算cellHeight,返回cellHeight

正确思路:

  1.自定义UITableViewCell,继承自UITableViewCell

  2.自定义UITableViewCell中重写- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

  目的:给自定义cell添加子控件

    2.1.注意:该方法中调用父类同名方法

    2.2.该方法中为自定义cell创建子控件,并把这些子控件添加到自定义cell的contentView中

    2.3.给自定义cell添加子控件属性,保住子控件的命,在其他方法中也能访问子控件

    2.4.返回自定义cell

  3.重写- (void)layoutSubviews

  目的:布局子控件

    3.1.注意:一定要调用[super layoutSubviews];

    3.2.该方法中根据需求计算子控件的frame

  4.给自定义cell添加数据模型属性,重写该属性的set方法

  目的:在数据源方法- (UITableViewCell *)tableView:cellForRowAtIndexPath:中直接为cell的模型属性赋值,更加MVC

  注意:该数据模型属性一定要声明在.h文件中,为了外界能够调用

    4.1.重写自定义cell的模型属性的set方法

    4.2.在set方法中给自定义cell的子控件赋值

    4.3.根据实际情况判断子控件的显示和隐藏

  5.实现UITableView的delegate方法- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

  目的:在该方法中再次计算每个子控件的高度

    5.1.根据实际情况(某些子控件的显示或者隐藏)确定cell的高度

    5.2.返回计算出来的cell的高度

 如下图,为项目的目录结构:

数据模型:

/***********************数据模型.h文件***********************/
#import <UIKit/UIKit.h>

@interface WSBlogItem : UIView
/** 名称 */
@property (nonatomic,copy) NSString *name;
/** 内容 */
@property (nonatomic,copy) NSString *text;
/** 头像 */
@property (nonatomic,copy) NSString *icon;
/** 配图 */
@property (nonatomic,copy) NSString *picture;
/** 是否会员 */
@property (nonatomic,assign,getter=isVip) BOOL vip;

// 苹果规范:一般一个类工厂方法对应一个自定义构造方法
/** 自定义构造方法 (字典->模型)*/
- (instancetype)initWithDict:(NSDictionary *)dict;
/** 类工厂方法 (字典->模型) */
+ (instancetype)blogItemWithDict:(NSDictionary *)dict;

@end
/***********************数据模型.m文件***********************/
#import "WSBlogItem.h"

@implementation WSBlogItem

- (instancetype)initWithDict:(NSDictionary *)dict
{
    if (self = [super init]) {
        self.name = dict[@"name"];
        self.text = dict[@"text"];
        self.icon = dict[@"icon"];
        self.picture = dict[@"picture"];
        self.vip = dict[@"vip"];
    }

    return self;
}

+ (instancetype)blogItemWithDict:(NSDictionary *)dict
{
    // 调用自定义构造方法
    return [[self alloc] initWithDict:dict];
}
@end

自定义cell:

/***********************自定义cell.h文件***********************/
#import <UIKit/UIKit.h>
#import "WSBlogItem.h"

@interface WSBlogCell : UITableViewCell
/** 自定义cell的数据模型属性 */ @property (nonatomic,strong) WSBlogItem *blogItem;
@end
/***********************自定义cell.m文件***********************/
#import "WSBlogCell.h"
#define WSNameFont [UIFont systemFontOfSize:17]
#define WSTextFont [UIFont systemFontOfSize:14]

@interface WSBlogCell ()
/** 名称Label */
@property(nonatomic,strong) UILabel *WSNameLabel;
/** 文本Label */
@property(nonatomic,strong) UILabel *WSTextLabel;
/** 头像ImageView */
@property(nonatomic,strong) UIImageView *WSIconView;
/** 配图ImageView */
@property(nonatomic,strong) UIImageView *WSPictureView;
/** 是否vip的Label */
@property(nonatomic,strong) UIImageView *WSVipView;

@end

@implementation WSBlogCell

#pragma mark - 重写initWithStyle:方法 (创建、添加子控件)
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        
        // 名称Label
        UILabel *WSNameLabel = [[UILabel alloc] init];
        self.WSNameLabel = WSNameLabel;
        [self.contentView addSubview:WSNameLabel];
        
        // 文本Label
        UILabel *WSTextLabel = [[UILabel alloc] init];
        WSTextLabel.numberOfLines = 0; // 文字可以换行显示
        WSTextLabel.font = WSTextFont; // 不设置字体大小会导致文字不能完全显示(即使numberOfLines = 0)
        self.WSTextLabel = WSTextLabel;
        [self.contentView addSubview:WSTextLabel];
        
        // 是否vip的Label
        UIImageView *WSVipView = [[UIImageView alloc] init];
        self.WSVipView = WSVipView;
        [self.contentView addSubview:WSVipView];
        
        // 头像ImageView
        UIImageView *WSIconView = [[UIImageView alloc] init];
        self.WSIconView = WSIconView;
        [self.contentView addSubview:WSIconView];
        
        // 配图ImageView
        UIImageView *WSPictureView = [[UIImageView alloc] init];
        self.WSPictureView = WSPictureView;
        [self.contentView addSubview:WSPictureView];
        
    }
    return self;
}

#pragma mark - 布局子控件
- (void)layoutSubviews
{
    // 1.千万不能漏掉这句
    [super layoutSubviews];
    
    // 2.空算所有的子控件的frame
    CGFloat margin = 10;
    
    // 头像
    CGFloat iconX = margin;
    CGFloat iconY = margin;
    CGFloat iconWH = 30;
    CGRect iconFrame = CGRectMake(iconX, iconY, iconWH, iconWH);
    self.WSIconView.frame = iconFrame;
    
    // 昵称(姓名)
    CGFloat nameY = iconY;
    CGFloat nameX = CGRectGetMaxX(iconFrame) + margin;
    // 计算文字所占据的尺寸
    NSDictionary *nameAttrs = @{NSFontAttributeName : [UIFont systemFontOfSize:17]};
    CGSize nameSize = [self.WSNameLabel.text sizeWithAttributes:nameAttrs];
    CGRect nameFrame = (CGRect){{nameX, nameY}, nameSize};
    self.WSNameLabel.frame = nameFrame;
    
    // 会员图标
    if (self.blogItem.isVip) {
        CGFloat vipW = 14;
        CGFloat vipH = nameSize.height;
        CGFloat vipY = nameY;
        CGFloat vipX = CGRectGetMaxX(nameFrame) + margin;
        CGRect vipFrame = CGRectMake(vipX, vipY, vipW, vipH);
        self.WSVipView.frame = vipFrame;
    }

    // 文字
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(iconFrame) + margin;
    CGFloat textW = self.contentView.frame.size.width - 2 * textX;
    CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
    NSDictionary *textAttrs = @{NSFontAttributeName : WSTextFont};
    CGFloat textH = [self.blogItem.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textAttrs context:nil].size.height;
    CGRect textFrame = CGRectMake(textX, textY, textW, textH);
    self.WSTextLabel.frame = textFrame;
    
    // 配图
    if (self.blogItem.picture) {
        CGFloat pictureWH = 100;
        CGFloat pictureX = textX;
        CGFloat pictureY = CGRectGetMaxY(textFrame) + margin;
        CGRect pictureFrame = CGRectMake(pictureX, pictureY, pictureWH, pictureWH);
        self.WSPictureView.frame = pictureFrame;
    }
}

#pragma mark - 重写blogItem属性的set方法(内部对cell的子控件进行赋值)
- (void)setBlogItem:(WSBlogItem *)blogItem
{
    _blogItem = blogItem;
    
    // 对cell的子控件赋值
    self.WSNameLabel.text = blogItem.name;
    self.WSTextLabel.text = blogItem.text;
    self.WSIconView.image = [UIImage imageNamed:blogItem.icon];
    
    if (blogItem.vip) {
        // name颜色为黄色
        self.WSVipView.hidden = NO;
        self.WSNameLabel.textColor = [UIColor yellowColor];
    }else{
        // name颜色为黑色
        self.WSVipView.hidden = YES;
        self.WSNameLabel.textColor = [UIColor blackColor];
    }
    
    if (blogItem.picture) {
        // 有配图
        self.WSPictureView.hidden = NO;
        self.WSPictureView.image = [UIImage imageNamed:blogItem.picture];
        
    }else{
        // 无配图
        self.WSPictureView.hidden = YES;
    }
}

@end

控制器:

/***********************控制器.h文件***********************/
#import <UIKit/UIKit.h>

@interface ViewController : UITableViewController

@end
/***********************控制器.m文件***********************/
#import "ViewController.h"
#import "WSBlogItem.h"
#import "WSBlogCell.h"

@interface ViewController ()
// 注意:懒加载的对象必须是strong
/** 模型数组 */
@property(nonatomic,strong)NSArray *blogItems;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // tableView的行高由row自己决定,不是由cell决定
    self.tableView.rowHeight = 200;
}

#pragma mark - datasource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.blogItems.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 重用标识
    static NSString *ID = @"blogCell";
    // 重用
    WSBlogCell *cell = [self.tableView dequeueReusableCellWithIdentifier:ID];
    // tableView的缓存池中没有可以重用的cell就创建并设置重用标识
    if (!cell) {
        cell = [[WSBlogCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
        NSLog(@"newCell");
    }
    
    // 取出对应行的数据模型
    WSBlogItem *blogItem = self.blogItems[indexPath.row];
    // 调用cell的blogItem属性的set方法,给这个cell设置数据
    cell.blogItem = blogItem;
    
    // 返回设置好数据的cell
    return cell;
}

#pragma mark - delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    WSBlogItem *blogItem = self.blogItems[indexPath.row];
    
    CGFloat margin = 10;
    // 头像
    CGFloat iconX = margin;
    CGFloat iconY = margin;
    CGFloat iconWH = 30;
    CGRect iconFrame = CGRectMake(iconX, iconY, iconWH, iconWH);
//    self.WSIconView.frame = iconFrame;
    
    // 昵称(姓名)
    CGFloat nameY = iconY;
    CGFloat nameX = CGRectGetMaxX(iconFrame) + margin;
    // 计算文字所占据的尺寸
    NSDictionary *nameAttrs = @{NSFontAttributeName : [UIFont systemFontOfSize:17]};
    CGSize nameSize = [blogItem.text sizeWithAttributes:nameAttrs];
    CGRect nameFrame = (CGRect){{nameX, nameY}, nameSize};
    
    // 会员图标
    if (blogItem.isVip) {
        CGFloat vipW = 14;
        CGFloat vipH = nameSize.height;
        CGFloat vipY = nameY;
        CGFloat vipX = CGRectGetMaxX(nameFrame) + margin;
        CGRect vipFrame = CGRectMake(vipX, vipY, vipW, vipH);
    }
    
    // 文字
    CGFloat textX = iconX;
    CGFloat textY = CGRectGetMaxY(iconFrame) + margin;
    CGFloat textW = self.tableView.frame.size.width - 2 * textX;
    CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
    NSDictionary *textAttrs = @{NSFontAttributeName : [UIFont systemFontOfSize:14]};
    CGFloat textH = [blogItem.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textAttrs context:nil].size.height;
    CGRect textFrame = CGRectMake(textX, textY, textW, textH);
    
    // 配图
    if (blogItem.picture) {
        CGFloat pictureWH = 100;
        CGFloat pictureX = textX;
        CGFloat pictureY = CGRectGetMaxY(textFrame) + margin;
        CGRect pictureFrame = CGRectMake(pictureX, pictureY, pictureWH, pictureWH);
        return CGRectGetMaxY(pictureFrame) + margin;
    }else{
        return CGRectGetMaxY(textFrame) + margin;
    }
    
}
#pragma mark - lazyLoad
- (NSArray *)blogItems
{
    // 注意用 !_blogItems 的好处,相对于 _blogItems == nil
    if (!_blogItems) {
        // 注意不要用 self.blogItems,避免出现get方法循环调用
        _blogItems = [NSArray array];
        
        // 1.获取plist文件路径
        NSString *path = [[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil];
        // 2.加载plist
        NSArray *arrDict = [NSArray arrayWithContentsOfFile:path];
        // 3.字典数组->模型数组
        // 3.1.创建临时可变数组
        NSMutableArray *arrM = [NSMutableArray array];
        for (NSDictionary *dict in arrDict) {
            WSBlogItem *blogItem = [WSBlogItem blogItemWithDict:dict];
            [arrM addObject:blogItem];
        }
        // 3.2.可变数组->不可变数组(为了安全)
        // 注意arrM的作用范围,不要写到{}外面
        _blogItems = [arrM copy];
    }
    // 4.返回
    return _blogItems;
}

@end

运行效果图:

 
    优化:因为在heightForRowAtIndexPath:方法中和layoutSubviews方法中计算了两次子控件的frame,而系统先会 调用heightForRowAtIndexPath:,所以可以把heightForRowAtIndexPath:计算的子控件的frame(包括子 控件的高度)保存到模型中,在layoutSubviews中直接用模型中的子控的frame。不需要再次在layoutSubviews中计算子控件的 frame。

    再次优化:
    给模型添加cellHeight属性
    在heightForRowAtIndexPath:中直接返回模型的cellHeight属性
    在模型的.h文件中重写cellHeight属性的get方法,在get方法中计算子控件的frame(包括子控件的高度),最后返回cellHeight。

 数据模型做了如下修改:

#import <UIKit/UIKit.h>

@interface WSBlogItem : UIView
/***********************文字/图片数据***********************/
/** 名称 */
@property (nonatomic,copy) NSString *name;
/** 内容 */
@property (nonatomic,copy) NSString *text;
/** 头像 */
@property (nonatomic,copy) NSString *icon;
/** 配图 */
@property (nonatomic,copy) NSString *picture;
/** 是否会员 */
@property (nonatomic,assign,getter=isVip) BOOL vip;

/***********************frame数据***********************/

@property (nonatomic,assign) CGRect nameFrame;
@property (nonatomic,assign) CGRect textFrame;
@property (nonatomic,assign) CGRect iconFrame;
@property (nonatomic,assign) CGRect pictureFrame;
@property (nonatomic,assign) CGRect vipFrame;

/** cell的高度 */
@property (nonatomic,assign) CGFloat cellHeight;
/***********************自定义方法***********************/ // 苹果建议:一般一个类工厂方法对应一个自定义构造方法 /** 自定义构造方法 (字典->模型)*/ - (instancetype)initWithDict:(NSDictionary *)dict; /** 类工厂方法 (字典->模型) */ + (instancetype)blogItemWithDict:(NSDictionary *)dict; @end
#import "WSBlogItem.h"
#define WSTextFont [UIFont systemFontOfSize:14]

@implementation WSBlogItem

- (instancetype)initWithDict:(NSDictionary *)dict
{
    if (self = [super init]) {
        self.name = dict[@"name"];
        self.text = dict[@"text"];
        self.icon = dict[@"icon"];
        self.picture = dict[@"picture"];
        self.vip = dict[@"vip"];
    }
    return self;
}

+ (instancetype)blogItemWithDict:(NSDictionary *)dict
{
    // 调用自定义构造方法
    return [[self alloc] initWithDict:dict];
}

#pragma mark - 重写cellHeight的get方法
- (CGFloat)cellHeight
{
    if (_cellHeight == 0) {
        
        // 计算所有的子控件的frame和高度
        CGFloat margin = 10;
        
        // 头像
        CGFloat iconX = margin;
        CGFloat iconY = margin;
        CGFloat iconWH = 30;
        CGRect iconFrame = CGRectMake(iconX, iconY, iconWH, iconWH);
        self.iconFrame = iconFrame;
        
        // 昵称(姓名)
        CGFloat nameY = iconY;
        CGFloat nameX = CGRectGetMaxX(iconFrame) + margin;
        // 计算文字所占据的尺寸
        NSDictionary *nameAttrs = @{NSFontAttributeName : [UIFont systemFontOfSize:17]};
        CGSize nameSize = [self.name sizeWithAttributes:nameAttrs];
        CGRect nameFrame = (CGRect){{nameX, nameY}, nameSize};
        self.nameFrame = nameFrame;
        
        // 会员图标
        if (self.isVip) {
            CGFloat vipW = 14;
            CGFloat vipH = nameSize.height;
            CGFloat vipY = nameY;
            CGFloat vipX = CGRectGetMaxX(nameFrame) + margin;
            CGRect vipFrame = CGRectMake(vipX, vipY, vipW, vipH);
            self.vipFrame = vipFrame;
        }
        
        // 文字
        CGFloat textX = iconX;
        CGFloat textY = CGRectGetMaxY(iconFrame) + margin;
        CGFloat textW = [UIScreen mainScreen].bounds.size.width - 2 * textX;
        CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
        NSDictionary *textAttrs = @{NSFontAttributeName : WSTextFont};
        CGFloat textH = [self.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textAttrs context:nil].size.height;
        CGRect textFrame = CGRectMake(textX, textY, textW, textH);
        self.textFrame = textFrame;
        
        // 配图
        if (self.picture) {// 有配图
            CGFloat pictureWH = 100;
            CGFloat pictureX = textX;
            CGFloat pictureY = CGRectGetMaxY(textFrame) + margin;
            CGRect pictureFrame = CGRectMake(pictureX, pictureY, pictureWH, pictureWH);
            self.pictureFrame = pictureFrame;
            
            // cell的真实高度参考图片的高度
            _cellHeight = CGRectGetMaxY(pictureFrame) + margin;
        }else{// 无配图
            // cell的真实高度参考文字的高度
            _cellHeight = CGRectGetMaxY(textFrame) + margin;
        }
    }
    
    return _cellHeight;
}
@end

自定义cell.m文件做了如下修改:

#pragma mark - 布局子控件
- (void)layoutSubviews
{
    // 1.千万不能漏掉这句
    [super layoutSubviews];
    
    self.WSNameLabel.frame = self.blogItem.nameFrame;
    self.WSTextLabel.frame = self.blogItem.textFrame;
    self.WSIconView.frame = self.blogItem.iconFrame;
    self.WSPictureView.frame = self.blogItem.pictureFrame;
    self.WSVipView.frame = self.blogItem.vipFrame;
}
#pragma mark - 重写blogItem属性的set方法(内部对cell的子控件进行赋值)
- (void)setBlogItem:(WSBlogItem *)blogItem
{
    _blogItem = blogItem;
    
    // 对cell的子控件赋值
    self.WSNameLabel.text = blogItem.name;
    self.WSTextLabel.text = blogItem.text;
    self.WSIconView.image = [UIImage imageNamed:blogItem.icon];
    
    if (blogItem.vip) {
        // name颜色为黄色
        self.WSVipView.hidden = NO;
        self.WSNameLabel.textColor = [UIColor redColor];
    }else{
        // name颜色为黑色
        self.WSVipView.hidden = YES;
        self.WSNameLabel.textColor = [UIColor blackColor];
    }
    
    if (blogItem.picture) {
        // 有配图
        self.WSPictureView.hidden = NO;
        self.WSPictureView.image = [UIImage imageNamed:blogItem.picture];
        
    }else{
        // 无配图
        self.WSPictureView.hidden = YES;
    }
}

控制器.m文件做了如下修改:

#pragma mark - delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    WSBlogItem *blogItem = self.blogItems[indexPath.row];
    
    return blogItem.cellHeight;
}

其实,可以把- (void)layoutSubviews布局子控件的工作交给cell的数据模型的set方法做,因为- (void)setBlogItem:(WSBlogItem *)blogItem在- (void)layoutSubviews之后调用,这样就省去了- (void)layoutSubviews方法的重写和调用

#pragma mark - 布局子控件
//- (void)layoutSubviews
//{
//    // 1.千万不能漏掉这句
//    [super layoutSubviews];
//    
//    self.WSNameLabel.frame = self.blogItem.nameFrame;
//    self.WSTextLabel.frame = self.blogItem.textFrame;
//    self.WSIconView.frame = self.blogItem.iconFrame;
//    self.WSPictureView.frame = self.blogItem.pictureFrame;
//    self.WSVipView.frame = self.blogItem.vipFrame;
//}

#pragma mark - 重写blogItem属性的set方法(内部对cell的子控件进行赋值)
- (void)setBlogItem:(WSBlogItem *)blogItem
{
    _blogItem = blogItem;
    
    // 对cell的子控件赋值
    self.WSNameLabel.text = blogItem.name;
    self.WSTextLabel.text = blogItem.text;
    self.WSIconView.image = [UIImage imageNamed:blogItem.icon];
    
    if (blogItem.vip) {
        // name颜色为黄色
        self.WSVipView.hidden = NO;
        self.WSNameLabel.textColor = [UIColor redColor];
    }else{
        // name颜色为黑色
        self.WSVipView.hidden = YES;
        self.WSNameLabel.textColor = [UIColor blackColor];
    }
    
    if (blogItem.picture) {
        // 有配图
        self.WSPictureView.hidden = NO;
        self.WSPictureView.image = [UIImage imageNamed:blogItem.picture];
        
    }else{
        // 无配图
        self.WSPictureView.hidden = YES;
    }

    // 设置子控件的frame
    self.WSNameLabel.frame = self.blogItem.nameFrame;
    self.WSTextLabel.frame = self.blogItem.textFrame;
    self.WSIconView.frame = self.blogItem.iconFrame;
    self.WSPictureView.frame = self.blogItem.pictureFrame;
    self.WSVipView.frame = self.blogItem.vipFrame;

}

@end

方法调用顺序总结 2->1->3:

1.- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

  该方法中因为要知道cell的高度,所以该方法返回之前会先调用第2个方法

  该方法中因为要给cell设置数据,所以会调用cell的数据模型属性的set方法- (void)setBlogItem:(WSBlogItem *)blogItem

    - (void)setBlogItem:(WSBlogItem *)blogItem中给cell的子控件属性设置
2.- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 计算子控件的frame然后保存下来

  该方法要返回cell的高度,所以会调用数据模型的cellHeight属性的get方法- (CGFloat)cellHeight

    - (CGFloat)cellHeight中计算子控件的frame并计算cell的高度,然后返回_cellHeight
3.- (void)layoutSubviews
  调用该方法时候,上面的2个方法已经调用完成,所以子控件frame已经有值

 

posted @ 2015-09-01 02:20  oneSong  阅读(670)  评论(0编辑  收藏  举报