自定义UITableViewCell新浪微博
自定义
UITableViewCell的步骤:
1.
新建一个继承自
UITableViewCell
的类
2. 重写 initWithStyle:reuseIdentifier: 方法
添加所有需要显示的子控件 ( 不需要设置子控件的数据和 frame, 子控件要添加到 contentView 中 )
进行子控件一次性的属性设置 ( 有些属性只需要设置一次 , 比如字体 \ 固定的图片 )
3. 提供 2 个模型
数据模型 : 存放文字数据 \ 图片数据
frame 模型 : 存放数据模型 \ 所有子控件的 frame\cell 的高度
4. cell 拥有一个 frame 模型 ( 不要直接拥有数据模型 )
5. 重写 frame 模型属性的 setter 方法 : 在这个方法中设置子控件的显示数据和 frame
6.f rame 模型数据的初始化已经采取懒加载的方式 ( 每一个 cell 对应的 frame 模型数据只加载一次 )
2. 重写 initWithStyle:reuseIdentifier: 方法
添加所有需要显示的子控件 ( 不需要设置子控件的数据和 frame, 子控件要添加到 contentView 中 )
进行子控件一次性的属性设置 ( 有些属性只需要设置一次 , 比如字体 \ 固定的图片 )
3. 提供 2 个模型
数据模型 : 存放文字数据 \ 图片数据
frame 模型 : 存放数据模型 \ 所有子控件的 frame\cell 的高度
4. cell 拥有一个 frame 模型 ( 不要直接拥有数据模型 )
5. 重写 frame 模型属性的 setter 方法 : 在这个方法中设置子控件的显示数据和 frame
6.f rame 模型数据的初始化已经采取懒加载的方式 ( 每一个 cell 对应的 frame 模型数据只加载一次 )
步骤一:根据
plist文件,创建Model层数据。
@property
(
nonatomic
,
copy
)
NSString
*text;
//
正文
@property ( nonatomic , copy ) NSString *icon; // 头像
@property ( nonatomic , copy ) NSString *picture; // 图片
@property ( nonatomic , copy ) NSString *name; // name
@property ( nonatomic , assign ) BOOL vip; // vip
+ ( instancetype )weiboWithDict:( NSDictionary *)dict;
- ( instancetype )initWithDict:( NSDictionary *)dict;
@property ( nonatomic , copy ) NSString *icon; // 头像
@property ( nonatomic , copy ) NSString *picture; // 图片
@property ( nonatomic , copy ) NSString *name; // name
@property ( nonatomic , assign ) BOOL vip; // vip
+ ( instancetype )weiboWithDict:( NSDictionary *)dict;
- ( instancetype )initWithDict:( NSDictionary *)dict;
+ (
NSArray
*)
weibos
;
- (
instancetype
)initWithDict:(
NSDictionary
*)dict
{
if ( self = [ super init ]) {
[ self setValuesForKeysWithDictionary :dict];
}
return self ;
}
+ ( instancetype )weiboWithDict:( NSDictionary *)dict
{
return [[ self alloc ] initWithDict :dict];
}
{
if ( self = [ super init ]) {
[ self setValuesForKeysWithDictionary :dict];
}
return self ;
}
+ ( instancetype )weiboWithDict:( NSDictionary *)dict
{
return [[ self alloc ] initWithDict :dict];
}
+ (
NSArray
*)weibos
{
NSArray *array = [ NSArray arrayWithContentsOfFile :[[ NSBundle mainBundle ] pathForResource : @"statuses.plist" ofType : nil ]];
NSMutableArray *arrayM = [ NSMutableArray array ];
for ( NSDictionary *dict in array) {
[arrayM addObject :[ self statusWithDict :dict]];
}
return arrayM;
}
{
NSArray *array = [ NSArray arrayWithContentsOfFile :[[ NSBundle mainBundle ] pathForResource : @"statuses.plist" ofType : nil ]];
NSMutableArray *arrayM = [ NSMutableArray array ];
for ( NSDictionary *dict in array) {
[arrayM addObject :[ self statusWithDict :dict]];
}
return arrayM;
}
步骤二:实现数据源方法,查看数据是否能显示出来。
- (
NSArray
*)weibos
{
if ( _weibos == nil ) {
_weibos = [ SUNWeiboItem weibos ];
{
if ( _weibos == nil ) {
_weibos = [ SUNWeiboItem weibos ];
}
return _weibos ;
}
return _weibos ;
}
#pragma mark -
数据源方法
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
{
return self . statuses . count ;
}
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
static NSString *ID = @"cell" ;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
if (cell == nil ) {
cell = [[ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier :ID];
}
SUNWeiboItem *weiboItem = self . statuses [indexPath. row ];
cell. textLabel . text = weiboItem. name ;
return cell;
}
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
{
return self . statuses . count ;
}
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
static NSString *ID = @"cell" ;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
if (cell == nil ) {
cell = [[ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier :ID];
}
SUNWeiboItem *weiboItem = self . statuses [indexPath. row ];
cell. textLabel . text = weiboItem. name ;
return cell;
}
步骤三:创建自定义
SUNWeiboCell
,
继承自
UITableViewCell,
根据需求,确定控件,并定义属性。
@property
(
nonatomic
,
strong
)
UIImageView
*iconView;
@property ( nonatomic , strong ) UILabel *nameView;
@property ( nonatomic , strong ) UIImageView *vipView;
@property ( nonatomic , strong ) UILabel *textView;
@property ( nonatomic , strong ) UIImageView *pictureView;
@property ( nonatomic , strong ) UILabel *nameView;
@property ( nonatomic , strong ) UIImageView *vipView;
@property ( nonatomic , strong ) UILabel *textView;
@property ( nonatomic , strong ) UIImageView *pictureView;
步骤四、
用
getter
方法完成控件的实例化,只创建并添加到
contentView
,不处理位置。
/**
姓名字体
*/
#define kNameFont [UIFont systemFontOfSize: 14 ]
/** 正文字体 */
#define kTextFont [UIFont systemFontOfSize: 16 ]
#define kNameFont [UIFont systemFontOfSize: 14 ]
/** 正文字体 */
#define kTextFont [UIFont systemFontOfSize: 16 ]
- (
UIImageView
*)iconView
{
if ( _iconView == nil ) {
_iconView = [[ UIImageView alloc ] init ];
[ self . contentView addSubview : _iconView ];
}
return _iconView ;
}
- ( UILabel *)nameView
{
if ( _nameView == nil ) {
_nameView = [[ UILabel alloc ] init ];
// 默认字体是 17 号
_nameView . font = kNameFont ;
[ self . contentView addSubview : _nameView ];
}
return _nameView ;
}
注意:
{
if ( _iconView == nil ) {
_iconView = [[ UIImageView alloc ] init ];
[ self . contentView addSubview : _iconView ];
}
return _iconView ;
}
- ( UILabel *)nameView
{
if ( _nameView == nil ) {
_nameView = [[ UILabel alloc ] init ];
// 默认字体是 17 号
_nameView . font = kNameFont ;
[ self . contentView addSubview : _nameView ];
}
return _nameView ;
}
注意:
UILabel中默认的字体是17号。
- ( UIImageView *)vipView
{
if ( _vipView == nil ) {
_vipView = [[ UIImageView alloc ] init ];
_vipView . image = [ UIImage imageNamed : @"vip" ];
_vipView . hidden = YES ;
[ 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 ;
}
注意:
numberOfLines属性是换行的意思。
- ( UIImageView *)pictureView
{
if ( _pictureView == nil ) {
_pictureView = [[ UIImageView alloc ] init ];
[ self . contentView addSubview : _pictureView ];
}
return _pictureView ;
}
- ( UIImageView *)pictureView
{
if ( _pictureView == nil ) {
_pictureView = [[ UIImageView alloc ] init ];
[ self . contentView addSubview : _pictureView ];
}
return _pictureView ;
}
步骤五:在自定义cell里面,
定义一个模型属性,通过
setter
方法,设置
cell
的显示。
@property
(
nonatomic
,
strong
)
SUNWeiboItem
*weiboItem;
- (
void
)setWeiboItem:(
SUNWeiboItem
*)weiboItem
{
_weiboItem = weiboItem;
// 1> 设置数据
[ self settingData ];
// 2> 设置位置
[ self settingFrame ];
}
{
_weiboItem = weiboItem;
// 1> 设置数据
[ self settingData ];
// 2> 设置位置
[ self settingFrame ];
}
注意:
在主方法中,代码不宜过长。
/**
设置数据
*/
- ( void )settingData
{
// 头像
self . iconView . image = [ UIImage imageNamed : self . weiboItem . icon ];
// 姓名
self . nameView . text = self . weiboItem . name ;
// vip( 可选的 )
if ( self . weiboItem . vip ) {
self . vipView . hidden = NO ;
self . nameView . textColor = [ UIColor redColor ];
} else {
self . vipView . hidden = YES ;
self . nameView . textColor = [ UIColor blackColor ];
}
// 正文
self . textView . text = self . weiboItem . text ;
// 配图 ( 可选参数 )
if ( self . weiboItem . picture . length > 0 ) {
self . pictureView . hidden = NO ;
self . pictureView . image = [ UIImage imageNamed : self . weiboItem . picture ];
} else {
self . pictureView . hidden = YES ;
}
}
/** 设置位置 */
- ( void )settingFrame
{
// 0. 定义间距
CGFloat padding = 10 ;
// 1. 头像
CGFloat iconX = padding;
CGFloat iconY = padding;
CGFloat iconW = 30 ;
CGFloat iconH = 30 ;
self . iconView . frame = CGRectMake (iconX, iconY, iconW, iconH);
// 2. 姓名大小由文字的长度来决定
NSDictionary *nameDict = @{ NSFontAttributeName : kNameFont } ;
CGRect nameFrame = [ weiboItem . name boundingRectWithSize : CGSizeMake ( MAXFLOAT , MAXFLOAT ) options : NSStringDrawingUsesLineFragmentOrigin attributes :nameDict context : nil ];
nameFrame. origin . x = CGRectGetMaxX ( self . iconView . frame ) + padding;
nameFrame. origin . y = padding + ( self . iconView . bounds . size . height - nameFrame. size . height ) * 0.5 ;
self . nameView . frame = nameFrame;
注意:
- ( void )settingData
{
// 头像
self . iconView . image = [ UIImage imageNamed : self . weiboItem . icon ];
// 姓名
self . nameView . text = self . weiboItem . name ;
// vip( 可选的 )
if ( self . weiboItem . vip ) {
self . vipView . hidden = NO ;
self . nameView . textColor = [ UIColor redColor ];
} else {
self . vipView . hidden = YES ;
self . nameView . textColor = [ UIColor blackColor ];
}
// 正文
self . textView . text = self . weiboItem . text ;
// 配图 ( 可选参数 )
if ( self . weiboItem . picture . length > 0 ) {
self . pictureView . hidden = NO ;
self . pictureView . image = [ UIImage imageNamed : self . weiboItem . picture ];
} else {
self . pictureView . hidden = YES ;
}
}
/** 设置位置 */
- ( void )settingFrame
{
// 0. 定义间距
CGFloat padding = 10 ;
// 1. 头像
CGFloat iconX = padding;
CGFloat iconY = padding;
CGFloat iconW = 30 ;
CGFloat iconH = 30 ;
self . iconView . frame = CGRectMake (iconX, iconY, iconW, iconH);
// 2. 姓名大小由文字的长度来决定
NSDictionary *nameDict = @{ NSFontAttributeName : kNameFont } ;
CGRect nameFrame = [ weiboItem . name boundingRectWithSize : CGSizeMake ( MAXFLOAT , MAXFLOAT ) options : NSStringDrawingUsesLineFragmentOrigin attributes :nameDict context : nil ];
nameFrame. origin . x = CGRectGetMaxX ( self . iconView . frame ) + padding;
nameFrame. origin . y = padding + ( self . iconView . bounds . size . height - nameFrame. size . height ) * 0.5 ;
self . nameView . frame = nameFrame;
注意:
文字的大小,最好和vip图标的宽度一致,这样比较容易计算出vip的位置。
// vip 图标
CGFloat vipX = CGRectGetMaxX ( self . nameView . frame ) + padding;
CGFloat vipY = self . nameView . frame . origin . y ;
CGFloat vipW = 14 ;
CGFloat vipH = 14 ;
self . vipView . frame = CGRectMake (vipX, vipY, vipW, vipH);
// 正文
NSDictionary *textDict = @{ NSFontAttributeName : kTextFont } ;
CGRect textFrame = [ weiboItem . text boundingRectWithSize : CGSizeMake ( 300 , MAXFLOAT ) options : NSStringDrawingUsesLineFragmentOrigin attributes :textDict context : nil ];
textFrame. origin . x = padding;
textFrame. origin . y = CGRectGetMaxY ( self . iconView . frame ) + padding;
self . textView . frame = textFrame;
注意:
// vip 图标
CGFloat vipX = CGRectGetMaxX ( self . nameView . frame ) + padding;
CGFloat vipY = self . nameView . frame . origin . y ;
CGFloat vipW = 14 ;
CGFloat vipH = 14 ;
self . vipView . frame = CGRectMake (vipX, vipY, vipW, vipH);
// 正文
NSDictionary *textDict = @{ NSFontAttributeName : kTextFont } ;
CGRect textFrame = [ weiboItem . text boundingRectWithSize : CGSizeMake ( 300 , MAXFLOAT ) options : NSStringDrawingUsesLineFragmentOrigin attributes :textDict context : nil ];
textFrame. origin . x = padding;
textFrame. origin . y = CGRectGetMaxY ( self . iconView . frame ) + padding;
self . textView . frame = textFrame;
注意:
boundingRectWithSize属性,如果文字不换行的话,可以设置为CGSizeMake(MAXFLOAT, MAXFLOAT)。如果文字需要换行的话,需要指定宽度,即CGSizeMake(300, MAXFLOAT)。
CGFloat cellHeight;
if ( weiboItem . picture . length > 0 ) {
// 配图
CGFloat pictureX = padding;
CGFloat pictureY = CGRectGetMaxY (textFrame) + padding;
CGFloat pictureW = 100 ;
CGFloat pictureH = 100 ;
self . pictureView . frame = CGRectMake (pictureX, pictureY, pictureW, pictureH);
CGFloat cellHeight;
if ( weiboItem . picture . length > 0 ) {
// 配图
CGFloat pictureX = padding;
CGFloat pictureY = CGRectGetMaxY (textFrame) + padding;
CGFloat pictureW = 100 ;
CGFloat pictureH = 100 ;
self . pictureView . frame = CGRectMake (pictureX, pictureY, pictureW, pictureH);
注意:
一般在自定义表格中的配图的宽度和高度是固定死的,这样容易计算配图的位置。
cellHeight =
CGRectGetMaxY
(
self
.
pictureView
.
frame
) + padding;
} else {
cellHeight = CGRectGetMaxY ( self . textView . frame ) + padding;
}
}
} else {
cellHeight = CGRectGetMaxY ( self . textView . frame ) + padding;
}
}
注意:
1.boundingRectWithSize计算给定文本字符串所占的区域,返回值是一个x,y = 0的CGRect,w,h是计算好的宽高。
2.如果要计算多行的准确高度,需要传入NSStringDrawingUsesLineFragmentOrigin选项。
3.attributes属性用于指定字体的相关属性的字典,UIKit框架中的第一个头文件。
3.attributes属性用于指定字体的相关属性的字典,UIKit框架中的第一个头文件。
4.context: nil
步骤六、在控制器实现
UITableView的代理方法调整为
#pragma mark -
数据源方法
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
{
return self . statuses . count ;
}
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
{
return self . statuses . count ;
}
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
NSLog
(
@“222222222222222222"
);
static NSString *ID = @"cell" ;
SUNWeiboCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
if (cell == nil ) {
cell = [[ SUNWeiboCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier :ID];
}
cell. weiboItem = self . statuses [indexPath. row ];
return cell;
}
static NSString *ID = @"cell" ;
SUNWeiboCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
if (cell == nil ) {
cell = [[ SUNWeiboCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier :ID];
}
cell. weiboItem = self . statuses [indexPath. row ];
return cell;
}
/**
计算单元格行高
*/
- ( CGFloat )tableView:( UITableView *)tableView heightForRowAtIndexPath:( NSIndexPath *)indexPath
{
NSLog ( @"111111111111111111111" );
return 200 ;
}
- ( CGFloat )tableView:( UITableView *)tableView heightForRowAtIndexPath:( NSIndexPath *)indexPath
{
NSLog ( @"111111111111111111111" );
return 200 ;
}
问题分析:
1.在加载表格数据调用此方法前- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath,会首先调用- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath方法计算所有单元格的高度,而此时单元格尚未被实例化。
1.在加载表格数据调用此方法前- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath,会首先调用- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath方法计算所有单元格的高度,而此时单元格尚未被实例化。
2.因此获取每一行的高度,不能直接从cell对象中获取,因为那时候还没创建cell对象,因此我们需要另外创建一个模型,用来管理cell内部所有子控件的frame和cell的总高度。
那么,在加载数据模型时,应该就可以准确地计算出每一行的准确行高了。
解决办法:创建 SUNWeiboFrameItem 模型,专门处理行高的计算。
步骤七、 创建 SUNWeiboFrameItem 模型,专门处理行高的计算。
/**
专门计算所有控件位置
*/
@interface SUNWeiboFrameItem : NSObject
@property ( nonatomic , assign ) CGRect iconImageViewF; // 头像 View
@property ( nonatomic , assign ) CGRect titleLabelF; // nameView
@property ( nonatomic , assign ) CGRect pictureImageF; // 图片 View
@property ( nonatomic , assign ) CGRect zwLabelF; // 正文 Label
@property ( nonatomic , assign ) CGRect vipImageViewF; // vip
/** 行高 */
@property ( nonatomic , assign ) CGFloat cellHeight;
/** 所有控件的尺寸都可以通过 Status 来计算得出 */
@property ( nonatomic , strong ) SUNWeiboItem *weiboItem;
+ ( NSArray *)weiboFrames;
@end
@interface SUNWeiboFrameItem : NSObject
@property ( nonatomic , assign ) CGRect iconImageViewF; // 头像 View
@property ( nonatomic , assign ) CGRect titleLabelF; // nameView
@property ( nonatomic , assign ) CGRect pictureImageF; // 图片 View
@property ( nonatomic , assign ) CGRect zwLabelF; // 正文 Label
@property ( nonatomic , assign ) CGRect vipImageViewF; // vip
/** 行高 */
@property ( nonatomic , assign ) CGFloat cellHeight;
/** 所有控件的尺寸都可以通过 Status 来计算得出 */
@property ( nonatomic , strong ) SUNWeiboItem *weiboItem;
+ ( NSArray *)weiboFrames;
@end
注意:创建 SUNWeiboFrameItem模型,通过setter方法计算行高。
- (
void
)setWeiboItem:(
SUNWeiboItem
*)weiboItem
{
_weiboItem = weiboItem;
// 0. 定义间距
CGFloat padding = 10 ;
// 1. 头像
CGFloat iconX = padding;
CGFloat iconY = padding;
CGFloat iconW = 30 ;
CGFloat iconH = 30 ;
self . iconImageViewF = CGRectMake (iconX, iconY, iconW, iconH);
// 2. 姓名大小由文字的长度来决定
NSDictionary *nameDict = @{ NSFontAttributeName : kNameFont } ;
CGRect nameFrame = [ self . weiboItem . name boundingRectWithSize : CGSizeMake ( MAXFLOAT , MAXFLOAT ) options : NSStringDrawingUsesLineFragmentOrigin attributes :nameDict context : nil ];
nameFrame. origin . x = CGRectGetMaxX ( self . iconImageViewF ) + padding;
nameFrame. origin . y = padding + ( self . iconImageViewF . size . height - nameFrame. size . height ) * 0.5 ;
self . titleLabelF = nameFrame;
// vip 图标
CGFloat vipX = CGRectGetMaxX ( self . titleLabelF ) + padding;
CGFloat vipY = self . titleLabelF . origin . y ;
CGFloat vipW = 14 ;
CGFloat vipH = 14 ;
self . vipImageViewF = CGRectMake (vipX, vipY, vipW, vipH);
// 正文
NSDictionary *textDict = @{ NSFontAttributeName : kTextFont } ;
CGRect textFrame = [ self . weiboItem . text boundingRectWithSize : CGSizeMake ( 300 , MAXFLOAT ) options : NSStringDrawingUsesLineFragmentOrigin attributes :textDict context : nil ];
textFrame. origin . x = padding;
textFrame. origin . y = CGRectGetMaxY ( self . iconImageViewF ) + padding;
self . zwLabelF = textFrame;
if ( self . weiboItem . picture . length > 0 ) {
// 配图
CGFloat pictureX = padding;
CGFloat pictureY = CGRectGetMaxY (textFrame) + padding;
CGFloat pictureW = 100 ;
CGFloat pictureH = 100 ;
self . pictureImageF = CGRectMake (pictureX, pictureY, pictureW, pictureH);
self . cellHeight = CGRectGetMaxY ( self . pictureImageF ) + padding;
} else {
self . cellHeight = CGRectGetMaxY ( self . zwLabelF ) + padding;
}
}
{
_weiboItem = weiboItem;
// 0. 定义间距
CGFloat padding = 10 ;
// 1. 头像
CGFloat iconX = padding;
CGFloat iconY = padding;
CGFloat iconW = 30 ;
CGFloat iconH = 30 ;
self . iconImageViewF = CGRectMake (iconX, iconY, iconW, iconH);
// 2. 姓名大小由文字的长度来决定
NSDictionary *nameDict = @{ NSFontAttributeName : kNameFont } ;
CGRect nameFrame = [ self . weiboItem . name boundingRectWithSize : CGSizeMake ( MAXFLOAT , MAXFLOAT ) options : NSStringDrawingUsesLineFragmentOrigin attributes :nameDict context : nil ];
nameFrame. origin . x = CGRectGetMaxX ( self . iconImageViewF ) + padding;
nameFrame. origin . y = padding + ( self . iconImageViewF . size . height - nameFrame. size . height ) * 0.5 ;
self . titleLabelF = nameFrame;
// vip 图标
CGFloat vipX = CGRectGetMaxX ( self . titleLabelF ) + padding;
CGFloat vipY = self . titleLabelF . origin . y ;
CGFloat vipW = 14 ;
CGFloat vipH = 14 ;
self . vipImageViewF = CGRectMake (vipX, vipY, vipW, vipH);
// 正文
NSDictionary *textDict = @{ NSFontAttributeName : kTextFont } ;
CGRect textFrame = [ self . weiboItem . text boundingRectWithSize : CGSizeMake ( 300 , MAXFLOAT ) options : NSStringDrawingUsesLineFragmentOrigin attributes :textDict context : nil ];
textFrame. origin . x = padding;
textFrame. origin . y = CGRectGetMaxY ( self . iconImageViewF ) + padding;
self . zwLabelF = textFrame;
if ( self . weiboItem . picture . length > 0 ) {
// 配图
CGFloat pictureX = padding;
CGFloat pictureY = CGRectGetMaxY (textFrame) + padding;
CGFloat pictureW = 100 ;
CGFloat pictureH = 100 ;
self . pictureImageF = CGRectMake (pictureX, pictureY, pictureW, pictureH);
self . cellHeight = CGRectGetMaxY ( self . pictureImageF ) + padding;
} else {
self . cellHeight = CGRectGetMaxY ( self . zwLabelF ) + padding;
}
}
+ (
NSArray
*)weiboFrames
{
NSString *filePath = [[ NSBundle mainBundle ] pathForResource : @"statuses.plist" ofType : nil ];
NSArray *array = [ NSArray arrayWithContentsOfFile :filePath];
NSMutableArray *arrayM = [ NSMutableArray array ];
for ( NSDictionary *dict in array) {
SUNWeiboFrameItem *weiboFrameItem = [[ SUNWeiboFrameItem alloc ] init ];
weiboFrameItem. weiboItem = [ SUNWeiboItem weiboWithDict :dict];
[arrayM addObject :weiboFrameItem];
}
return arrayM;
}
/** 设置数据 */
- ( void )settingData
{
SUNWeiboItem *weiboItem = self . weiboFrameItem . weiboItem ;
// 头像
self . iconView . image = [ UIImage imageNamed :weiboItem. icon ];
// 姓名
self . nameView . text = weiboItem. name ;
// vip( 可选的 )
if (weiboItem. vip ) {
self . vipView . hidden = NO ;
self . nameView . textColor = [ UIColor redColor ];
} else {
self . vipView . hidden = YES ;
self . nameView . textColor = [ UIColor blackColor ];
}
// 正文
self . textView . text = weiboItem. text ;
// 配图 ( 可选参数 )
// imageNamed:nil CUICatalog: Invalid asset name supplied: (null), or invalid scale factor: 2.000000
if (weiboItem. picture . length > 0 ) {
self . pictureView . hidden = NO ;
self . pictureView . image = [ UIImage imageNamed :weiboItem. picture ];
} else {
self . pictureView . hidden = YES ;
}
}
/** 设置位置 */
- ( void )settingFrame
{
self . iconView . frame = self . weiboFrameItem . iconImageViewF ;
// 2. 姓名大小由文字的长度来决定
self . nameView . frame = self . weiboFrameItem . titleLabelF ;
// vip 图标
self . vipView . frame = self . weiboFrameItem . vipImageViewF ;
// 正文
self . textView . frame = self . weiboFrameItem . zwLabelF ;
if ( self . weiboFrameItem . weiboItem . picture . length > 0 ) {
// 配图
self . pictureView . frame = self . weiboFrameItem . pictureImageF ;
}
}
{
NSString *filePath = [[ NSBundle mainBundle ] pathForResource : @"statuses.plist" ofType : nil ];
NSArray *array = [ NSArray arrayWithContentsOfFile :filePath];
NSMutableArray *arrayM = [ NSMutableArray array ];
for ( NSDictionary *dict in array) {
SUNWeiboFrameItem *weiboFrameItem = [[ SUNWeiboFrameItem alloc ] init ];
weiboFrameItem. weiboItem = [ SUNWeiboItem weiboWithDict :dict];
[arrayM addObject :weiboFrameItem];
}
return arrayM;
}
注意:
所有的单元格控件的计算都是重复的,而且每次表格滚动,设置内容都会重新计算。
解决这个问题:
SUNWeiboFrameItem模型中,已经包含了 weiboItem属性。
目前控制器中的数组保存的是 weiboItem模型,将 weiboItem模型替换为SUNWeiboFrameItem模型{weiboItem,所有控件的位置},同样具有weiboItem模型。
SUNWeiboFrameItem模型中,已经包含了 weiboItem属性。
目前控制器中的数组保存的是 weiboItem模型,将 weiboItem模型替换为SUNWeiboFrameItem模型{weiboItem,所有控件的位置},同样具有weiboItem模型。
步骤八、重构调整
SUNWeiboItem
和
SUNWeiboFrameItem
在
SUNWeiboItem模型中删除
weibos数组。
在
SUNWeiboFrameItem添加
weiboFrames数组。
步骤九、重构控制器
实现
UITableView的代理方法调整为
- (
NSArray
*)weiboFrames
{
if ( _weiboFrames == nil ) {
_weiboFrames = [ SUNWeiboFrameItem weiboFrames ];
}
return _weiboFrames ;
}
{
if ( _weiboFrames == nil ) {
_weiboFrames = [ SUNWeiboFrameItem weiboFrames ];
}
return _weiboFrames ;
}
注意:
weiboFrames数组要改变成SUNWeiboFrameItem的模型数据。
#pragma mark -
数据源方法
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
{
return self . weiboFrames . count ;
}
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
static NSString *ID = @"cell" ;
SUNWeiboCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
if (cell == nil ) {
cell = [[ SUNWeiboCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier :ID];
}
SUNWeiboFrameItem *weiboFrameItem = self . weiboFrames [indexPath. row ];
cell. weiboItem = weiboFrameItem. weiboItem ;
return cell;
}
/** 计算单元格行高 */
- ( CGFloat )tableView:( UITableView *)tableView heightForRowAtIndexPath:( NSIndexPath *)indexPath
{
NSLog ( @"111111111111111111111" );
SUNWeiboFrameItem *weiboFrameItem = self . weiboFrames [indexPath. row ];
return weiboFrameItem. cellHeight ;
}
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
{
return self . weiboFrames . count ;
}
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
static NSString *ID = @"cell" ;
SUNWeiboCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
if (cell == nil ) {
cell = [[ SUNWeiboCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier :ID];
}
SUNWeiboFrameItem *weiboFrameItem = self . weiboFrames [indexPath. row ];
cell. weiboItem = weiboFrameItem. weiboItem ;
return cell;
}
/** 计算单元格行高 */
- ( CGFloat )tableView:( UITableView *)tableView heightForRowAtIndexPath:( NSIndexPath *)indexPath
{
NSLog ( @"111111111111111111111" );
SUNWeiboFrameItem *weiboFrameItem = self . weiboFrames [indexPath. row ];
return weiboFrameItem. cellHeight ;
}
问题分析:
cell中的控件的位置计算,依然是自己计算的。
解决办法:将cell中的status替换为statusFrame就可以拿到控件位置。
解决办法:将cell中的status替换为statusFrame就可以拿到控件位置。
步骤十、重构
自定义
SUNWeiboCell,将
SUNWeiboItem模型数据替换为
SUNWeiboFrameItem模型数据。
@property
(
nonatomic
,
strong
)
SUNWeiboItem
*weiboItem;
- (
void
)setWeiboFrameItem:(
SUNWeiboFrameItem
*)weiboFrameItem
{
_weiboFrameItem = weiboFrameItem;
// 1> 设置数据
[ self settingData ];
// 2> 设置位置
[ self settingFrame ];
}
{
_weiboFrameItem = weiboFrameItem;
// 1> 设置数据
[ self settingData ];
// 2> 设置位置
[ self settingFrame ];
}
/** 设置数据 */
- ( void )settingData
{
SUNWeiboItem *weiboItem = self . weiboFrameItem . weiboItem ;
// 头像
self . iconView . image = [ UIImage imageNamed :weiboItem. icon ];
// 姓名
self . nameView . text = weiboItem. name ;
// vip( 可选的 )
if (weiboItem. vip ) {
self . vipView . hidden = NO ;
self . nameView . textColor = [ UIColor redColor ];
} else {
self . vipView . hidden = YES ;
self . nameView . textColor = [ UIColor blackColor ];
}
// 正文
self . textView . text = weiboItem. text ;
// 配图 ( 可选参数 )
// imageNamed:nil CUICatalog: Invalid asset name supplied: (null), or invalid scale factor: 2.000000
if (weiboItem. picture . length > 0 ) {
self . pictureView . hidden = NO ;
self . pictureView . image = [ UIImage imageNamed :weiboItem. picture ];
} else {
self . pictureView . hidden = YES ;
}
}
/** 设置位置 */
- ( void )settingFrame
{
self . iconView . frame = self . weiboFrameItem . iconImageViewF ;
// 2. 姓名大小由文字的长度来决定
self . nameView . frame = self . weiboFrameItem . titleLabelF ;
// vip 图标
self . vipView . frame = self . weiboFrameItem . vipImageViewF ;
// 正文
self . textView . frame = self . weiboFrameItem . zwLabelF ;
if ( self . weiboFrameItem . weiboItem . picture . length > 0 ) {
// 配图
self . pictureView . frame = self . weiboFrameItem . pictureImageF ;
}
}
步骤十一、
重构控制器
实现
UITableView的代理方法调整为
- (
UITableViewCell
*)tableView:(
UITableView
*)tableView cellForRowAtIndexPath:(
NSIndexPath
*)indexPath
{
static NSString *ID = @"cell" ;
SUNWeiboCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
if (cell == nil ) {
cell = [[ SUNWeiboCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier :ID];
}
cell. weiboFrameItem = self . weiboFrames [indexPath. row ];
return cell;
}
{
static NSString *ID = @"cell" ;
SUNWeiboCell *cell = [tableView dequeueReusableCellWithIdentifier :ID];
if (cell == nil ) {
cell = [[ SUNWeiboCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier :ID];
}
cell. weiboFrameItem = self . weiboFrames [indexPath. row ];
return cell;
}