1.新建一个继承自UITableViewCell的类
2.重写initWithStyle:reuseIdentifier:方法
Ø 添加所有需要显示的子控件(不需要设置子控件的数据和frame, 子控件要添加到contentView中)
Ø 进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)
3.提供2个模型
Ø 数据模型: 存放文字数据\图片数据
Ø frame模型: 存放数据模型\所有子控件的frame\cell的高度
4.cell拥有一个frame模型(不要直接拥有数据模型)
5.重写frame模型属性的模型数据的setter方法: 在这个方法中设置子控件的显示数据和frame
6.在viewControl中frame模型数据的初始化依旧采取懒加载的方式(每一个cell对应的frame模型数据只加载一次)
为什么要设立frame模型?
提高性能,防止需要多次进行计算,一次性计算好。方便其他程序使用Cell的某些尺寸数据。
注意:frame模型中的frame属性一般只用来读,而不去改变,最好在定义属性时,加上readonly。若加上readonly,则对该属性赋值不能使用点语法,只能直接对成员变量进行赋值,类似于“_变量 = 赋值;”
eg:
1)代码自定义的cell:
MJStatusCell.h文件:
#import <UIKit/UIKit.h>
#import "MJStatusFrame.h"
@interface MJStatusCell : UITableViewCell
/**
* Frame模型数据
*/
//@property(nonatomic,strong) MJStatus *status;
@property (nonatomic,strong) MJStatusFrame*statusFrame;
+ (instancetype)statusCellWithTableView:(UITableView*)tableView;
@end
MJStatusCell.m文件:
#import "MJStatusCell.h"
// 昵称的字体
#define MJNameFont [UIFont systemFontOfSize:14]
// 正文的字体
#define MJTextFont [UIFont systemFontOfSize:15]
@interface MJStatusCell()
/**
* 头像
*/
@property (weak, nonatomic) UIImageView *iconView;
/**
* 昵称
*/
@property (weak, nonatomic) UILabel *nameView;
/**
* 会员标识
*/
@property (weak, nonatomic) UIImageView *vipView;
/**
* 正文
*/
@property (weak, nonatomic) UILabel *textView;
/**
* 配图
*/
@property (weak, nonatomic) UIImageView *pictureView;
@end
@implementation MJStatusCell
// 创建Cell的类方法
+(instancetype)statusCellWithTableView:(UITableView *)tableView
{
static NSString *id = @"statusCell";
MJStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:id];
if(cell == nil) {
cell = [[MJStatusCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:id];
}
return cell;
}
// Cell初始化方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self= [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self) {
// 1.添加头像(注意不要直接把self.iconView添加到contentView中)
UIImageView *vip = (UIImageView *)[[UIImageView alloc]init];
[self.contentView addSubview:vip];
self.iconView = vip;
//self.iconView.backgroundColor = [UIColorredColor];
//self.iconView.frame = CGRectMake(10, 10, 30,30);
// 2.添加昵称
UILabel *label = (UILabel *)[[UILabel alloc]init];
label.font = MJNameFont;
//label.backgroundColor = [UIColor blueColor];
[self.contentView addSubview:label];
self.nameView = label;
// 3.添加会员标识
UIImageView *vipView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"vip"]];
[self.contentView addSubview:vipView];
self.vipView = vipView;
//self.vipView.backgroundColor = [UIColorredColor];
// 4.添加正文
UILabel *text = (UILabel *)[[UILabel alloc]init];
text.font = MJTextFont;
text.numberOfLines = 0;
[self.contentView addSubview:text];
self.textView = text;
// 5.添加配图
UIImageView *pictureView = (UIImageView *)[[UIImageView alloc]init];
[self.contentView addSubview:pictureView];
self.pictureView = pictureView;
//self.pictureView.backgroundColor = [UIColorredColor];
//NSLog(@"##initWithStyle 执行中");
}
return self;
}
- (void)setStatusFrame:(MJStatusFrame *)statusFrame
{
_statusFrame = statusFrame;
// 1.设置内容
MJStatus *status = _statusFrame.status;
// NSLog(@"##icon:%@",status.icon);
// NSLog(@"##iconFrame:%f",statusFrame.iconFrame.size.height);
// NSLog(@"##textView:%@",status.name);
// NSLog(@"##textFrame:%f",statusFrame.textFrame.size.height);
NSString *imgPath = [NSString stringWithFormat:@"icon/%@",status.icon];
NSString *path = [[NSBundle mainBundle]pathForResource:imgPath ofType:nil];
self.iconView.image = [UIImage imageWithContentsOfFile:path];
self.nameView.text = status.name;
if(status.vip) {
[self.vipView setHidden:NO];
}else
{
[self.vipView setHidden:YES];
}
self.textView.text = status.text;
if(status.picture) {
self.pictureView.hidden = NO;
NSString *imgPath = [NSString stringWithFormat:@"image/%@",status.picture];
NSString *path = [[NSBundle mainBundle]pathForResource:imgPath ofType:nil];
self.pictureView.image = [UIImage imageWithContentsOfFile:path];
}else
{
self.pictureView.hidden = YES;
}
// 2.设置Frame
self.iconView.frame = _statusFrame.iconFrame;
self.nameView.frame = _statusFrame.nameFrame;
self.vipView.frame = _statusFrame.vipFrame;
self.textView.frame = _statusFrame.textFrame;
//self.textView.frame = CGRectMake(10, 30,300,100);
if(status.picture) {
self.pictureView.frame = _statusFrame.pictureFrame;
}
}
@end
2)数据模型:
MJStatus.h文件:
#import <Foundation/Foundation.h>
@interface MJStatus : NSObject
@property (nonatomic,copy) NSString *text;
@property (nonatomic,copy) NSString *icon;
@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) BOOL vip;
@property (nonatomic,copy) NSString *picture;
- (instancetype)initWithDict:(NSDictionary*)dict;
+ (instancetype)statusWithDict:(NSDictionary*)dict;
@end
MJStatus.m文件:
#import "MJStatus.h"
@implementation MJStatus
- (instancetype)initWithDict:(NSDictionary*)dict
{
if(self = [super init]) {
[selfsetValuesForKeysWithDictionary:dict];
}
return self;
}
+ (instancetype)statusWithDict:(NSDictionary*)dict
{
return [[self alloc]initWithDict:dict];
}
@end
3)Frame模型:
MJStatusFrame.h文件:
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import "MJStatus.h"
@interface MJStatusFrame : NSObject
/**
* 头像Frame
*/
@property (nonatomic,assign,readonly) CGRecticonFrame;
/**
* 昵称Frame
*/
@property (nonatomic,assign,readonly) CGRectnameFrame;
/**
* 会员标识Frame
*/
@property (nonatomic,assign,readonly) CGRectvipFrame;
/**
* 正文Frame
*/
@property (nonatomic,assign,readonly) CGRecttextFrame;
/**
* 配图Frame
*/
@property (nonatomic,assign,readonly) CGRectpictureFrame;
/**
* 模型数据
*/
@property (nonatomic,strong) MJStatus*status;
/**
* cell的高度
*/
@property (nonatomic,assign) CGFloatcellHight;
@end
MJStatusFrame.m文件:
#import "MJStatusFrame.h"
#import <UIKit/UIKit.h>
// 昵称的字体
#defineMJNameFont [UIFont systemFontOfSize:14]
// 正文的字体
#defineMJTextFont [UIFont systemFontOfSize:15]
@implementationMJStatusFrame
/**
* 计算文字尺寸
*
* @paramtext 需要计算尺寸的文字
* @paramfont 文字的字体
* @parammaxSize 文字的最大尺寸
*/
- (CGSize)sizeWithText:(NSString *)textfont:(UIFont *)font maxSize:(CGSize)maxSize
{
NSDictionary *attrs = @{NSFontAttributeName : font};
return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
}
//status的赋值方法
- (void)setStatus:(MJStatus*)status
{
_status = status;
// 计算Frame
// 1.控件间距
CGFloat padding = 10;
// 2.头像Frame
CGFloat iconX = padding;
CGFloat iconY = padding;
CGFloat iconW = 30;
CGFloat iconH = 30;
_iconFrame = CGRectMake(iconX,iconY, iconW, iconH);
// 3.昵称Frame
CGFloat nameX = CGRectGetMaxX(_iconFrame) +padding;
CGSize nameSize = [self sizeWithText:self.status.name font:MJNameFont maxSize:CGSizeMake(MAXFLOAT, MAXFLOAT)];
CGFloat nameY = (CGRectGetMaxY(_iconFrame) -padding - nameSize.height) * 0.5 +padding;
CGFloat nameW= nameSize.width;
CGFloat nameH = nameSize.height;
_nameFrame = CGRectMake(nameX,nameY, nameW, nameH);
// 4.会员标识Frame
CGFloat vipX = CGRectGetMaxX(_nameFrame) +padding;
CGFloat vipY = (CGRectGetMaxY(_iconFrame) -padding - 14) * 0.5 +padding;
CGFloat vipH = 14;
CGFloat vipW = 14;
_vipFrame = CGRectMake(vipX,vipY, vipW, vipH);
// 5.正文Frame
CGFloat textX = padding;
CGFloat textY = CGRectGetMaxY(_iconFrame) +padding;
CGSize textSize = [self sizeWithText:self.status.text font:MJTextFont maxSize:CGSizeMake(360, MAXFLOAT)];
CGFloat textH = textSize.height;
CGFloat textW = textSize.width;
_textFrame = CGRectMake(textX,textY, textW, textH);
// 6.配图Frame
if (_status.picture) {
CGFloatpictureX = padding;
CGFloatpictureY = CGRectGetMaxY(_textFrame) + padding;
CGFloatpictureH = 360;
CGFloatpictureW = 360;
_pictureFrame = CGRectMake(pictureX,pictureY, pictureW, pictureH);
}
// 7.高度
if (status.picture) {
_cellHight = CGRectGetMaxY(_pictureFrame) +padding;
}else
{
_cellHight = CGRectGetMaxY(_textFrame) +padding;
}
}
@end
4)ViewController.m控制器文件
#import "ViewController.h"
#import "MJStatusFrame.h"
#import "MJStatusCell.h"
@interface ViewController ()
/**
* 模型数据数组
*/
@property (nonatomic,strong) NSArray*statusFrames;
@end
@implementationViewController
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading theview, typically from a nib.
}
//statusesFrames的懒加载
-(NSArray*)statusFrames
{
if (_statusFrames == nil) {
NSString *path= [[NSBundle mainBundle]pathForResource:@"statuses.plist" ofType:nil];
NSArray *array= [NSArray arrayWithContentsOfFile:path];
NSMutableArray*mutArray = [NSMutableArray array];
for (NSDictionary *dict inarray){
MJStatus*status = [MJStatus statusWithDict:dict];
MJStatusFrame *frame= [[MJStatusFrame alloc]init];
frame.status =status;
[mutArray addObject:frame];
}
_statusFrames =mutArray;
}
return _statusFrames;
}
#pragmamark 数据源方法
// 设置每一组的行数
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return self.statusFrames.count;
}
// 设置每一行的显示内容
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
// 1.创建Cell
MJStatusCell *statusCell = [MJStatusCell statusCellWithTableView:tableView];
// NSLog(@"frame模型数据打印:%@",self.statusFrames[0]);
// 2.传递模型数据
statusCell.statusFrame = self.statusFrames[indexPath.row];
return statusCell;
}
#pragmamark 代理方法
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
MJStatusFrame *frame = self.statusFrames[indexPath.row];
return frame.cellHight;
}
@end