matlab 判断cell11是否非空,11-自定义cell(2种方法)

第一种方法 :使用代码创建

分析:

(1)重写initWithStyle方法,在这个方法里创建控件或者尺寸约束(其实控件约束一般写在layoutSubviews里)。

(2)在layoutSubviews方法里设置尺寸

(3)重写模型的set方法

重写模型的set方法:

先声明模型类型,接受模型数据

@class XMGTopic;

@interface XMGTopicCell : UITableViewCell

/** 模型数据 */

@property (nonatomic, strong) XMGTopic *topic;

@end

代码:

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

{

if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

// 增加顶部的控件,并且设置约束

// ...

// 增加底部的控件,并且设置约束

// ...

}

return self;

}

/*

- (void)layoutSubviews

{

[super layoutSubviews];

// 设置顶部和底部控件的frame

}*/

- (void)setTopic:(XMGTopic *)topic

{

_topic = topic;

// 设置顶部和底部控件的具体数据(比如文字数据、图片数据)

}

@end

在Controller里创建cell并导入数据也有2种方法:

第一种:不常用(最基本的创建cell方法)

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

{

static NSString *ID = @"cell";

// 缓存池去取

XMGTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

if (cell == nil) { // 缓存池没有,创建

cell = [[XMGTopicCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];

}

// 导入数据

cell.topic = self.topics[indexPath.row];

return cell;

}

第二种:通过注册,常用

注册的功能是:去缓存池取cell,若没有创建cell

/* cell的重用标识 */

static NSString * const XMGTopicCellId = @"XMGTopicCellId";

// 注册cell, registerClass:代码注册,registerNib:xib注册

[self.tableView registerClass:[XMGTopicCell class] forCellReuseIdentifier:XMGTopicCellId];

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

{

XMGTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGTopicCellId];

// 导入数据

cell.topic = self.topics[indexPath.row];

return cell;

}

第二种方法:使用xib创建

分析:

(1)在- (void)awakeFromNib中进行控件设置

(2)重写模型的set方法

代码:

- (void)awakeFromNib

{

self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mainCellBackground"]];

}

- (void)setTopic:(XMGTopic *)topic

{

_topic = topic;

// 顶部控件的数据

[self.profileImageView sd_setImageWithURL:[NSURL URLWithString:topic.profile_image] placeholderImage:[UIImage imageNamed:@"defaultUserIcon"]];

self.nameLabel.text = topic.name;

self.passtimeLabel.text = topic.passtime;

self.text_label.text = topic.text;

// 底部按钮的文字

[self setupButtonTitle:self.dingButton number:topic.ding placeholder:@"顶"];

[self setupButtonTitle:self.caiButton number:topic.cai placeholder:@"踩"];

[self setupButtonTitle:self.repostButton number:topic.repost placeholder:@"分享"];

[self setupButtonTitle:self.commentButton number:topic.comment placeholder:@"评论"];

}

在Controller里注册cell并导入数据2种方法

第一种:通过mainBundle

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

{

static NSString *ID = @"cell";

// 缓存池去取

XMGTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

if (cell == nil) { // 缓存池没有,创建

cell = [[[NSBundle mainBundle] loadNibNamed:self owner:nil options:nil] firstObject];

}

// 导入数据

cell.topic = self.topics[indexPath.row];

return cell;

}

第二种:通过注册加载cell

/* cell的重用标识 */

static NSString * const XMGTopicCellId = @"XMGTopicCellId";

// 注册cell

UINib *nib = [UINib nibWithNibName:NSStringFromClass([XMGTopicCell class]) bundle:nil];

[self.tableView registerNib:nib forCellReuseIdentifier:XMGTopicCellId];

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

{

XMGTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGTopicCellId];

cell.topic = self.topics[indexPath.row];

return cell;

}

技巧:因为通过mainBundle加载资源,使用地方很多,可以将其封装在UIView的分类里

代码:

+ (instancetype)xmg_viewFromXib;

+ (instancetype)xmg_viewFromXib

{

return [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil].firstObject;

}

拓展:若有四种cell,其中有共同的部分,也有各自不同的部分,如何做?

分析:2种思路

第一种思路:父cell+子cell

分析:

因为xib无法继承,所以需要用纯代码或者顶部一个xib,底部一个xib,添加到cell上

在自定义子cell时,其它都相同,就是-setTopic时,需要先调用一下父控件的-setTopic方法,即将共同的顶部与底部先加载进来并设置好数据。

2220536c38bd

1.png

子cell的自定义代码如下:

@implementation XMGVoiceCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

{

if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

// 增加中间的声音控件,并且设置约束

// ...

self.backgroundColor = [UIColor greenColor];

}

return self;

}

/*

- (void)layoutSubviews

{

[super layoutSubviews];

// 设置中间声音控件的frame

}*/

- (void)setTopic:(XMGTopic *)topic

{

[super setTopic:topic];

// 设置中间声音控件的具体数据(比如文字数据、图片数据)

}

@end

第二种思路:只用一种cell

2220536c38bd

1.png

分析:

**(1)创建整体cell;

(2)中间内容: 自定义三种xib,分别是视频、语音、图片

(3)中间内容懒加载进整体cell中

**

2220536c38bd

1.png

@class XMGTopic;

@interface XMGTopicCell : UITableViewCell

/** 模型数据 */

@property (nonatomic, strong) XMGTopic *topic;

/* 中间控件 */

/** 图片控件 */

@property (nonatomic, weak) XMGTopicPictureView *pictureView;

/** 声音控件 */

@property (nonatomic, weak) XMGTopicVoiceView *voiceView;

/** 视频控件 */

@property (nonatomic, weak) XMGTopicVideoView *videoView;

@end

@implementation XMGTopicCell

#pragma mark - 懒加载

- (XMGTopicPictureView *)pictureView

{

if (!_pictureView) {

XMGTopicPictureView *pictureView = [XMGTopicPictureView xmg_viewFromXib];

[self.contentView addSubview:pictureView];

_pictureView = pictureView;

}

return _pictureView;

}

- (XMGTopicVoiceView *)voiceView

{

if (!_voiceView) {

XMGTopicVoiceView *voiceView = [XMGTopicVoiceView xmg_viewFromXib];

[self.contentView addSubview:voiceView];

_voiceView = voiceView;

}

return _voiceView;

}

- (XMGTopicVideoView *)videoView

{

if (!_videoView) {

XMGTopicVideoView *videoView = [XMGTopicVideoView xmg_viewFromXib];

[self.contentView addSubview:videoView];

_videoView = videoView;

}

return _videoView;

}

#pragma mark - 初始化

- (void)awakeFromNib

{

self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mainCellBackground"]];

}

- (void)setTopic:(XMGTopic *)topic

{

_topic = topic;

// 顶部控件的数据

UIImage *placeholder = [UIImage xmg_circleImageNamed:@"defaultUserIcon"];

[self.profileImageView sd_setImageWithURL:[NSURL URLWithString:topic.profile_image] placeholderImage:placeholder options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

// 图片下载失败,直接返回,按照它的默认做法

if (!image) return;

self.profileImageView.image = [image xmg_circleImage];

}];

self.nameLabel.text = topic.name;

self.passtimeLabel.text = topic.passtime;

self.text_label.text = topic.text;

// 底部按钮的文字

[self setupButtonTitle:self.dingButton number:topic.ding placeholder:@"顶"];

[self setupButtonTitle:self.caiButton number:topic.cai placeholder:@"踩"];

[self setupButtonTitle:self.repostButton number:topic.repost placeholder:@"分享"];

[self setupButtonTitle:self.commentButton number:topic.comment placeholder:@"评论"];

// 最热评论

if (topic.top_cmt.count) { // 有最热评论

self.topCmtView.hidden = NO;

NSDictionary *cmt = topic.top_cmt.firstObject;

NSString *content = cmt[@"content"];

if (content.length == 0) { // 语音评论

content = @"[语音评论]";

}

NSString *username = cmt[@"user"][@"username"];

self.topCmtLabel.text = [NSString stringWithFormat:@"%@ : %@", username, content];

} else { // 没有最热评论

self.topCmtView.hidden = YES;

}

// 中间的内容

if (topic.type == XMGTopicTypePicture) { // 图片

self.pictureView.hidden = NO;

self.voiceView.hidden = YES;

self.videoView.hidden = YES;

} else if (topic.type == XMGTopicTypeVoice) { // 声音

self.pictureView.hidden = YES;

self.voiceView.hidden = NO;

self.voiceView.topic = topic;

self.videoView.hidden = YES;

} else if (topic.type == XMGTopicTypeVideo) { // 视频

self.pictureView.hidden = YES;

self.voiceView.hidden = YES;

self.videoView.hidden = NO;

} else if (topic.type == XMGTopicTypeWord) { // 段子

self.pictureView.hidden = YES;

self.voiceView.hidden = YES;

self.videoView.hidden = YES;

}

}

- (void)layoutSubviews

{

[super layoutSubviews];

if (self.topic.type == XMGTopicTypePicture) { // 图片

self.pictureView.frame = self.topic.middleFrame;

} else if (self.topic.type == XMGTopicTypeVoice) { // 声音

self.voiceView.frame = self.topic.middleFrame;

} else if (self.topic.type == XMGTopicTypeVideo) { // 视频

self.videoView.frame = self.topic.middleFrame;

}

}

问题1:如何避免同一个cell的高度计算多次,即让同一个cel的高度只计算一次?

答案1:利用模型属性,额外增加计算cell高度的属性,重写cellHeight的getter方法。在cellHeight方法里判断是否计算过行高,已经计算过就返回)

流程分析:

当UITableView显示的时候,系统开始就会调用numberOfSections和numberOfRows方法,来知道行数和组数

然后调用heightForRow方法,计算所有cell的高度,计算出来tableView的contentsize,确定tableView的滑动范围。

再调用cellForRow方法,显示出cell

当屏幕来回滑动的时候,heightForRow方法会调用的频繁

解决上述问题,就定义一个模型属性,重写cellHeight的getter方法,已经计算过就返回

拓展:heightForRow这个方法的特点:

默认情况下,每次刷新表格的时候,有多少数据,这个方法就一次调用多少次 ---如:若有100条数据,每次reloadData,这个方法就会调用100次。

每当有cell进入屏幕范围,就会调用一次这个方法。

/* 额外增加的属性(并非服务器返回的属性,仅仅是为了提高开发效率) */

/** 根据当前模型计算出来的cell高度 */

@property (nonatomic, assign) CGFloat cellHeight;

/** 中间内容的frame */

@property (nonatomic, assign) CGRect middleFrame;

#import "XMGTopic.h"

@implementation XMGTopic

- (CGFloat)cellHeight

{

// 如果已经计算过,就直接返回

if (_cellHeight) return _cellHeight;

// 文字的Y值

_cellHeight += 55;

// 文字的高度

CGSize textMaxSize = CGSizeMake(XMGScreenW - 2 * XMGMarin, MAXFLOAT);

_cellHeight += [self.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]} context:nil].size.height + XMGMarin;

// 中间的内容

if (self.type != XMGTopicTypeWord) { // 中间有内容(图片、声音、视频)

CGFloat middleW = textMaxSize.width;

CGFloat middleH = middleW * self.height / self.width;

CGFloat middleY = _cellHeight;

CGFloat middleX = XMGMarin;

self.middleFrame = CGRectMake(middleX, middleY, middleW, middleH);

_cellHeight += middleH + XMGMarin;

}

// 最热评论

if (self.top_cmt.count) { // 有最热评论

// 标题

_cellHeight += 21;

// 内容

NSDictionary *cmt = self.top_cmt.firstObject;

NSString *content = cmt[@"content"];

if (content.length == 0) {

content = @"[语音评论]";

}

NSString *username = cmt[@"user"][@"username"];

NSString *cmtText = [NSString stringWithFormat:@"%@ : %@", username, content];

_cellHeight += [cmtText boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:16]} context:nil].size.height + XMGMarin;

}

// 工具条

_cellHeight += 35 + XMGMarin;

return _cellHeight;

}

@end

在Controller,返回每行模型对应的行高(在模型里,如果已经计算好,就会返回,若没有计算行高,就会继续执行计算行高)

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

XMGTopic * topic=self.topics[indexPath.row];

return topic.cellHeight;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值