Model:
JSStatuses.h:
#import
@interface JSStatuses : NSObject
@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSString *icon;
@property (nonatomic,copy) NSString *text;
@property (nonatomic,copy) NSString *picture;
@property (nonatomic,assign) BOOL vip;
- (instancetype)initWithDic:(NSDictionary *)dic;
+ (instancetype)jsStatusesWithDic:(NSDictionary *)dic;
@end
#import "JSStatuses.h"
@implementation JSStatuses
- (instancetype)initWithDic:(NSDictionary *)dic{
self = [super init];
if (self) {
[self setValuesForKeysWithDictionary:dic];
}
return self;
}
+ (instancetype)jsStatusesWithDic:(NSDictionary *)dic{
return [[self alloc]initWithDic:dic];
}
@end
JSStatusesFrame.h:
#import
#import
#import
@class JSStatuses;
@interface JSStatusesFrame : NSObject
@property (nonatomic,assign,readonly) CGRect nameF;
@property (nonatomic,assign,readonly) CGRect iconF;
@property (nonatomic,assign,readonly) CGRect textF;
@property (nonatomic,assign,readonly) CGRect vipF;
@property (nonatomic,assign,readonly) CGRect picF;
@property (nonatomic,assign,readonly) CGFloat cellHeight;
@property (nonatomic,strong) JSStatuses *statuses;
+ (NSMutableArray *)jSStatusesFrameList;
@end
JSStatusesFrame.m:
#import "JSStatusesFrame.h"
#import "JSStatuses.h"
#import "NSString+Tools.h"
#define kPadding 10
#define kIconW 30
#define kVipW 14
#define kPictureW 70
/** 姓名字体 */
#define kNameFont [UIFont systemFontOfSize:14]
/** 正文字体 */
#define kTextFont [UIFont systemFontOfSize:16]
//@synthesize iconF = _iconF;
/**
一旦重写了readonly属性的getter方法,_的成员变量就不存在了
如果还需要使用_成员变量,则需要使用@synthesize生成对应的成员变量
*/
@implementation JSStatusesFrame
- (void)setStatuses:(JSStatuses *)statuses{
_statuses = statuses;
//icon
CGFloat iconX = kPadding;
CGFloat iconY = kPadding;
_iconF = CGRectMake(iconX, iconY, kIconW,kIconW);
//name
// 姓名大小由文字的长度来决定
// boundingRectWithSize计算给定文本字符串所占的区域
// 返回值是一个x,y = 0的CGRect,w,h是计算好的宽高
//
// 如果要计算多行的准确高度,需要传入NSStringDrawingUsesLineFragmentOrigin选项
// dict用于指定字体的相关属性的字典,UIKit框架中的第一个头文件
// context: nil
CGSize nameSize = CGSizeMake(MAXFLOAT, MAXFLOAT);
NSDictionary *nameDic = @{NSFontAttributeName:kNameFont};
CGRect nameRect = [_statuses.name textSizeWithSize:nameSize attributes:nameDic];
nameRect.origin.x = CGRectGetMaxX(_iconF) + kPadding;
nameRect.origin.y = self.iconF.origin.y;
_nameF = nameRect;
//vip
CGFloat vipX = CGRectGetMaxX(_nameF) + kPadding;
CGFloat vipY = self.iconF.origin.y;
_vipF = CGRectMake(vipX, vipY, kVipW, kVipW);
//text正文
CGFloat textW = [UIScreen mainScreen].bounds.size.width - kPadding * 2;
CGSize textSize = CGSizeMake(textW, MAXFLOAT);
NSDictionary *textDic = @{NSFontAttributeName:kTextFont};
CGRect textRect = [_statuses.text textSizeWithSize:textSize attributes:textDic];
textRect.origin.x = kPadding;
textRect.origin.y = CGRectGetMaxY(_iconF) + kPadding;
_textF = textRect;
//picture
if (_statuses.picture.length) {
CGFloat picX = kPadding;
CGFloat picY = CGRectGetMaxY(_textF) + kPadding;
_picF = CGRectMake(picX, picY, kPictureW, kPictureW);
//计算行高
_cellHeight = CGRectGetMaxY(_picF) + kPadding;
}else{
_cellHeight = CGRectGetMaxY(_textF) +kPadding;
}
}
+ (NSMutableArray *)jSStatusesFrameList{
NSArray *statuses = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"statuses" ofType:@".plist" ]];
//字典转模型
NSMutableArray *statusesM = [NSMutableArray array];
for (int i = 0; i < statuses.count; i ++) {
JSStatusesFrame *statusesFrame = [[JSStatusesFrame alloc] init];
JSStatuses *status = [JSStatuses jsStatusesWithDic:statuses[i]];
statusesFrame.statuses = status;
[statusesM addObject:statusesFrame];
}
return statusesM;
}
@end
JSCell.h:
#import
@class JSStatusesFrame;
@interface JSCell : UITableViewCell
@property (nonatomic,strong) JSStatusesFrame *statusesFrame;
@end
#import "JSCell.h"
#import "JSStatusesFrame.h"
#import "JSStatuses.h"
#define kNameFont [UIFont systemFontOfSize:14];
#define kTextFont [UIFont systemFontOfSize:16];
@interface JSCell ()
@property (nonatomic,strong) UIImageView *iconView;
@property (nonatomic,strong) UILabel *nameView;
@property (nonatomic,strong) UIImageView *vipView;
@property (nonatomic,strong) UILabel *textView;
@property (nonatomic,strong) UIImageView *picView;
@end
@implementation JSCell
- (UIImageView *)iconView{
if (_iconView == nil) {
_iconView = [[UIImageView alloc] init];
[self.contentView addSubview:_iconView];
}
return _iconView;
}
- (UILabel *)nameView{
if (_nameView == nil) {
_nameView = [[UILabel alloc] init];
_nameView.font = kNameFont;
[self.contentView addSubview:_nameView];
}
return _nameView;
}
- (UIImageView *)vipView{
if (_vipView == nil) {
_vipView = [[UIImageView alloc] init];
[self.contentView addSubview:_vipView];
}
return _vipView;
}
- (UILabel *)textView{
if (_textView == nil) {
_textView = [[UILabel alloc] init];
_textView.font = kTextFont;
_textView.numberOfLines = 0;
[self.contentView addSubview:_textView];
}
return _textView;
}
- (UIImageView *)picView{
if (_picView == nil) {
_picView = [[UIImageView alloc] init];
[self.contentView addSubview:_picView];
}
return _picView;
}
//设置UI和Frame
- (void)setStatusesFrame:(JSStatusesFrame *)statusesFrame{
_statusesFrame = statusesFrame;
//设置数据
[self setStatusData];
//设置Frame
[self setFrame];
}
- (void)setStatusData{
//iconView
JSStatuses *statuses = self.statusesFrame.statuses;
self.iconView.image = [UIImage imageNamed:statuses.icon];
//nameView
self.nameView.text = statuses.name;
//vipView
if (statuses.vip) {
self.vipView.hidden = false;
self.nameView.textColor = [UIColor redColor];
self.vipView.image = [UIImage imageNamed:@"vip"];
}else{
self.vipView.hidden = true;
self.nameView.textColor = [UIColor blackColor];
}
//textView
self.textView.text = statuses.text;
//picView
if (self.statusesFrame.statuses.picture.length >0) {
self.picView.hidden = false;
self.picView.image = [UIImage imageNamed:statuses.picture];
}else{
self.picView.hidden = true;
}
}
-(void)setFrame{
//iconView
self.iconView.frame = self.statusesFrame.iconF;
//nameView
self.nameView.frame = self.statusesFrame.nameF;
//vipView
self.vipView.frame = self.statusesFrame.vipF;
//textView
self.textView.frame = self.statusesFrame.textF;
//picView
if(self.statusesFrame.statuses.picture.length >0)
self.picView.frame = self.statusesFrame.picF;
}
@end
NSString+Tools.h:
#import
#import
#import
// 使用分类,可以把常用的方法,不好记的方法都抽取出来,进行归纳总结
// 随着学习的深入,我们每个人都会建立一大套属于自己的分类库!
@interface NSString (Tools)
/**
* 计算当前字符串显示所需的实际frame,返回值的x = 0, y = 0
*/
- (CGRect)textSizeWithSize:(CGSize)size attributes:(NSDictionary *)attributes;
@end
NSString+Tools.m:
#import "NSString+Tools.h"
@implementation NSString (Tools)
-(CGRect)textSizeWithSize:(CGSize)size attributes:(NSDictionary *)attributes{
// self 就是调用当前成员方法的NSString对象
return [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
}
@end
#import "JSViewController.h"
#import "JSStatusesFrame.h"
#import "JSCell.h"
static NSString *ID = @"cell";
@interface JSViewController ()
@property (nonatomic,strong) NSMutableArray *statusesFrame;
@end
@implementation JSViewController
-(NSMutableArray *)statusesFrame{
if (_statusesFrame == nil) {
_statusesFrame = [JSStatusesFrame jSStatusesFrameList];
}
return _statusesFrame;
}
- (void)viewDidLoad {
[super viewDidLoad];
/**
*为tableView注册可重用单元格
*/
[self.tableView registerClass:[JSCell class] forCellReuseIdentifier:ID];
}
//设置数据源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.statusesFrame.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
/**
在Storyboard中指定了可重用标示符,同时指定了Cell的类是HMStatusCell
系统会为tableView注册一个原形Cell,专门用来做可重用单元格的,一旦缓冲区中不存在
可重用单元格,系统会使用原形Cell新实例化一个Cell用程序使用!
因此如果在,Storyboard中,注册了原形Cell,就不再需要 cell == nil的判断了
*/
//JSCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard
// 使用这个方法,要求一定注册可重用单元格,否则就会崩溃!
// 官方建议使用以下方法,利用程序的崩溃,及时发现问题
JSCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath];
JSStatusesFrame *statusFrame = self.statusesFrame[indexPath.row];
cell.statusesFrame = statusFrame;
return cell;
}
#pragma mark - 代理方法
/** 计算单元格行高 */
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
/**
计算行高的方法,会在加载表格数据时,有多少行计算多少次 contentSize
问题:此方法执行的时候,cell还没有被实例化!
但是:行高计算是在实例化cell时,通过设置status属性,计算的=>有了status模型,就可以知道行高!
问题:如何在cell实例化之前,获得行高?
解决方法:通过status可以计算得到行高!=》再建立一个模型,专门计算所有控件的位置
*/
JSStatusesFrame *statusesFrame = self.statusesFrame[indexPath.row];
return statusesFrame.cellHeight;
}
@end