封装frame模型:优化代码,在懒加载数据的时候,计算好每个控件的frame和 cell的行高。
CZWeibo.m
// CZWeibo.h
@interface CZWeibo :NSObject
@property(nanotomic, copy) NSString *text;
@property(nanotomic, copy) NSString *icon;
@property(nanotomic, copy) NSString *picture;
@property(nanotomic, copy) NSString *name;
@property(nanotomic, assign, getter=isVip) BOOL vip;
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)weiboWithDict:(NSDictionary *)dict;
@end
//-----------------------
// CZWeibo.m
- (instancetype)initWithDict:(NSDictionary *)dict{
// TODO
}
+ (instancetype)weiboWithDict:(NSDictionary *)dict{
// TODO
}
//-----------------------
@class CZWeibo;
@interface CZWeiboFrame : NSObject
@property(nanotomic, strong) CZWeibo *weibo; // 重写setter方法。
// 用来保存头像的frame
@property(nanotomic, assign, readonly) CGRect iconFrame;
@property(nanotomic, assign, readonly) CGRect nameFrame;
@property(nanotomic, assign, readonly) CGRect vipFrame;
@property(nanotomic, assign, readonly) CGRect textFrame;
@property(nanotomic, assign, readonly) CGRect picFrame;
// 行高
@property(nanotomic, assign, readonly) int rowHeight;
@end
//-----------------------
// 自定义字体的宏
#import "CZWeiboFrame.h"
#import <UIKit/UIKit.h>
#define nameFont [UIFont systemFontOfSize:12];
#define textFont [UIFont systemFontOfSize:14];
@implementation CZWeiboFrame
// 重写weibo的set方法,在里面计算frame
- (void)setWeibo:(CZWeibo *) weibo
{
_weibo = weibo;
// 计算每个控件的frame,宽高。
CGFloat margin = 10;
CZModel *model = self.weibo;
// 1.头像
CGFloat iconW = 35;
CGFloat iconH = 35;
CGFloat iconX = margin;
CGFloat iconY = margin;
_iconFrame = CGRectMake(iconX, iconY, iconW, iconH);
// 2.昵称
CGFloat nameX = CGRectGetMaxX(_iconFrame) + margin;
// 根据文字内容,动态计算label的高+宽
NSString *nickName = model.name; // 昵称
NSDictionary *attr = @{NSFontAttributeName: nameFont}; // 字体字典
// CGSize nameSize = [nickName boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options: NSStringDrawingUsesLineFragmentOrigin attributes: attr context:nil].size; // 获得文字显示的宽高
CGSize nameSize = [self sizeWithText:nickName andMaxSize:CGSizeMake(MAXFLOAT, MAXFLOAT) andFont:nameFont];
CGFloat nameW = nameSize.width;
CGFloat nameH = nameSize.height;
CGFloat nameY = iconY + (iconH - nameH) / 2;
_nameFrame = CGRectMake(nameX, nameY, nameW, nameH);
// 3.会员
CGFloat vipW = 10;
CGFloat vipH = 10;
CGFloat vipX = CGRectGetMaxX(_nameFrame) + margin;
CGFloat vipY = nameY;
_vipFrame = CGRectMake(vipX, vipY, vipW, vipH);
// 4.正文
CGFloat textX = iconX;
CGFloat textY = CGRectGetMaxX(self.imgViewIcon.frame) + margin;
CGSize textSize = [self sizeWithText:weibo.text andMaxSize:CGSizeMake(300, MAXFLOAT) andFont:textFont];
CGFloat textW = textSize.width;
CGFloat textH = textSize.height;
_textFrame = CGRectMake(textX, textY, textW, textH);
// 5.配图
CGFloat picW = 100;
CGFloat picH = 100;
CGFloat picX = iconX;
CGFloat picY = CGRectGetMaxY(_textFrame) + margin;
_picFrame = CGRectMake(picX, picY, picW, picH);
// 6.计算每行的高度。
CGFloat rowHeight = 0;
if(model.picture) {
// 行高 = 配图的maxY + margin
rowHeight = CGRectGetMaxY(_picFrame) + margin;
} else {
// 行高 = 正文的maxY + margin
rowHeight = CGRectGetMaxY(_textFrame) + margin;
}
// 给行高赋值。
_rowHeight = rowHeight;
}
// 根据给定的字符串,最大值的size,给定的字体。计算文字占据的大小。
- (CGSize)sizeWithText:(NSString *)text andMaxSize:(CGSize)maxSize andFont:(UIFont *) font {
NSDictionary *attr = @{NSFontAttributeName: font}; // 字体字典
return [text boundingRectWithSize:maxSize options: NSStringDrawingUsesLineFragmentOrigin
attributes: attr context:nil].size;
}
@end
自定义Cell01创建子控件:CZWeiboCell
// CZWeiboCell.h
#import <UIKit/UIKit.h>
@class CZWeiboFrame
@interface CZWeiboCell : UITableViewCell
// @property(nonatomic, strong) CZWeibo *weibo;
@property(nonatomic, strong) CZWeiboFrame *weiboFrame;
+ (instancetype)weiboCellWithTableView:(UITableView *)tableView;
@end
//---------------------
// CZWeiboCell.m
#import "CZWeiboCell.h"
#import "CZWeibo.h"
// 自定义字体的宏
#define nameFont [UIFont systemFontOfSize:12];
#define textFont [UIFont systemFontOfSize:14];
@interface CZWeiboCell ()
@property (nonatomic, weak) UIImageView *imgViewIcon;
@property (nonatomic, weak) UILabel *lblNickName;
@property (nonatomic, weak) UIImageView *imgViewVip;
@property (nonatomic, weak) UILabel *lblText;
@property (nonatomic, weak) UIImageView *imgViewPicture;
@end
@implementation CZWeiboCell
+(instancetype)weiboCellWithTableView:(UITableView *)tableView
{
static NSString *ID = @"weibo_cell";
CZWeiboCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if(cell == nil) {
cell = [[CZWeiboCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
return cell;
}
// 数据模型,改变成Frame模型。
- (void)setWeibo:(CZWeiboFrame *)weiboFrame {
_weiboFrame = weiboFrame;
// 设置子控件的数据
[self settingData];
// 设置子控件frame
[self settingFrame];
}
// 设置数据的方法
-(void)settingData {
CZModel *model = self.weiboFrame.weibo;
// (头像,昵称,会员,正文,配图)
self.imgViewIcon.image = [UIImage imageNamed:model.icon];
self.lblNickName.text = model.name;
// 会员图标:显示或 不显示
if(model.isVip) {
self.imageViewVip.hidden = NO;
} else {
self.imageViewVip.hidden = YES;
}
self.lblText.text = model.text;
// 配图,有配图就显示;无配图不设置,也不显示。
if(model.picture) {
self.imgViewPicture.image = [UIImage imageNamed:model.picture];
self.imageViewVip.hidden = NO;
} else { // 没配图。隐藏配图框。
self.imageViewVip.hidden = YES;
}
}
// 设置子控件frame
-(void)settingFrame {
self.imgViewIcon.frame = self.weiboFrame.iconFrame;
self.lblNickName.frame = self.weiboFrame.nameFrame;
self.imageViewVip.frame = self.weiboFrame.vipFrame;
self.lblText.frame = self.weiboFrame.textFrame;
self.imgViewPicture.frame = self.weiboFrame.picFrame;
}
// 重写方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
// 调用父类的方法,保证父类的方法被执行
if(self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// 创建5个子控件(头像,昵称,会员,正文,配图)
UIImageView *imgViewIcon = [[UIImageView alloc] init];
[self.contentView addSubView:imgViewIcon]
self.imgViewIcon = imgViewIcon; // 关联到cell中。
UILabel *lblNickName = [[UILabel alloc] init];
lblNickName.font = nameFont;
[self.contentView addSubView:lblNickName];
self.lblNickName = lblNickName;
UIImageView *imgViewVip = [[UIImageView alloc] init];
// vip图标,直接写死,所有vip用户的图标相同。
imgViewVip.image = [UIImage imageNamed:@"vip"];
[self.contentView addSubView:imgViewVip];
self.imgViewVip = imgViewVip;
UILabel *lblText = [[UILabel alloc] init];
lblText.font = textFont;
lblText.numberOfLines = 0; // 自动换行
self.lblText = lblText;
[self.contentView addSubView:lblText];
UIImageView *imgViewPicture = [[UIImageView alloc] init];
[self.contentView addSubView:imgViewPicture];
self.imgViewPicture = imgViewPicture;
}
return self;
}
- (void)awakeFromNib {
}
@end
#import "CZTableViewController.h"
@interface CZTableViewController ()
// 保存了CZWeiboFrame模型,而不是CZWeibo模型。
@property (nonatomic, strong) NSArray *weiboFrames;
@end
@implementation CZTableViewController
-(NSArray *) weiboFrames {
if(_weiboFrames == nil) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"weibos.plist" ofType:nil];
NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];
NSMutableArray *arrayModels = [NSMutableArray array];
for(NSDictionary *dict in arrayDict) {
CZWeibo *model = [CZWeibo weiboWithDict:dict];
// 创建一个空的模型。
CZWeiboFrame *modelFrame = [[CZWeiboFrame alloc] init];
modelFrame.weibo = model;
[arrayModels addObject:modelFrame];
}
_weiboFrames = arrayModels;
}
return _weiboFrames;
}
// 懒加载数据,计算每行的行高。所有子控件的frame,
-(NSArray *) weibos {
if(_weibos ==nil) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"weibos.plist" ofType:nil];
NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];
NSMutableArray *arrayModels = [NSMutableArray array];
for(NSDictionary *dict in arrayDict) {
CZWeibo *model = [CZWeibo weiboWithDict:dict];
[arrayModels addObject:model];
}
_weibos = arrayModels;
}
return _weibos;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section
{
return self.weiboFrames.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 1. 获取数据模型
CZWeiboCell *model = self.weiboFrames[indexPath.row];
// 2. 创建单元格。
/* static NSString *ID = @"weibo_cell";
CZWeiboCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if(cell == nil) {
cell = [[CZWeiboCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
} */
CZWeiboCell *cell = [CZWeiboCell weiboCellWithTableView:tableView];
cell.weiboFrame = model; // 3.设置单元格数据
return cell; // 4.返回单元格
}
// 返回每行的行高。
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CZWeiboFrame *weiboFrame = self.weiboFrames[indexPath.row];
return weiboFrame.rowHeight;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
@end
计算昵称的frame:
CGSize nameSize = [字符串对象 boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options: NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:font} context:nil];
2023/05/30 周二