最近有个界面需求长这样;
刚开始拿到这个界面的时候,我就懵逼了,这咋整啊;得,再怎么懵逼也得继续啊;
一,思路:
整体来说,先给他扣个tableView
吧,剩下的也就是怎么处理tableViewCell
了;再细看,整个cell
有两部分组成,一部分是主评论,一部分是副评论;主评论还好说,3个label
,1个imageView
;副评论就不行了,这副评论还是变化的,这可怎么办?
1,再细看,副评论也就是固定样式的view
的个数;想想自适应高度是不行了,只能看看如何得到高度,然后根据得到的高度来处理了;
2,副评论如何放在整个cell上面;
二,看来要获得整个cell的高度,少不了计算了,那么如何计算,以及如何让计算最可能的优化;之前是了解了下YYKit
框架,我想也许我能在子线程中计算整个我需要的height
,再有一点,YYkit
使用的是轻量级的layer
,由于整个项目使用的masonry
,并且我也不大想每个都计算,于是通过在拿到数据model
的时候,我顺便计算了我想要的几个label
的高度,至于其他的就是美工给的固定尺寸了;
解1: 这里我在子线程中初始化一个带有model
的layout
类,用来计算了我所需要的所有高度的数据;
LTYYCommentModel *model = [LTYYCommentModel yy_modelWithJSON:dic];
//这里传入了model和cellWidth,根据这两个数据我就可以计算所有我想要的高度;
[strongSelf.layoutsOfTableView addObject:[[LTYYCommentLayout alloc] initWithCommentModel:model withCellWidth:SCREEN_WIDTH - 20]];
如果不是太严谨的话,有时我只考虑了宽度的适配,毕竟大部分的view都是放在scrollView上展示的;
解2:副评论,我考虑的是把他打包好了,竟然都是一样的,那我就考虑是一个View
中放了若干个unitView
;由unitView
的个数决定View
的高度和hidden
;这样是可以实现,这个又有个问题了,我不想频繁的init
和add
,remove
;那么如何实现unitView
的复用呢?想想可以把用到的unitView
存起来,下次只要刷新label.text
和imageView.image
就可以啦,
@interface LTSubCommentUnit(){
UIImageView * _proImageView;
UILabel * _commentLabel;
}
@end
@implementation LTSubCommentUnit
- (instancetype)initWithModel:(LTYYReplyCommentModel *)model{
self = [super init];
if (self) {
_model = model;
_proImageView = [[UIImageView alloc] init];
_proImageView.layer.cornerRadius = 12 * kScaleNum;
_proImageView.layer.masksToBounds = YES;
[self addSubview:_proImageView];
_commentLabel = [[UILabel alloc] init];
_commentLabel.numberOfLines = 0;
[self addSubview:_commentLabel];
[self updateData];
}
return self;
}
- (void)setModel:(LTYYReplyCommentModel *)model{
_model = model;
[self updateData];
}
- (void)updateData{
[_proImageView setImageWithURL:_model.portrait.url placeholderImage:[UIImage imageNamed:@"metou"]];
NSString *comment = [NSString stringWithFormat:@"%@ : %@", _model.nickname, _model.replyContent];
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:comment attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12], NSForegroundColorAttributeName : HexColor(0xb3b3b3)}];
[attrStr setAttributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12],NSForegroundColorAttributeName : HexColor(0x666666)} range:NSMakeRange(0, _model.nickname.length)];
_commentLabel.attributedText = attrStr;
}
- (void)layoutSubviews{
_proImageView.frame = CGRectMake(43, 4, 24, 24);
_commentLabel.frame = CGRectMake(CGRectGetMaxX(_proImageView.frame) + 11, 10, self.width - (CGRectGetMaxX(_proImageView.frame) + 11 + 40), self.height - 10 * 2);
}
@end
@implementation LTSubCommentView
//赋值给副评论的model,刷新数据,当前array中如果没有unit,就再创建一个;
- (void)setReplyArray:(NSArray<LTYYReplyCommentModel *> *)replyArray{
_replyArray = replyArray;
for (int i = 0; i < replyArray.count; i ++) {
if (i < self.units.count) {
LTSubCommentUnit *unit = self.units[i];
unit.model = replyArray[i];
}else{
LTSubCommentUnit *unit = [[LTSubCommentUnit alloc] initWithModel:replyArray[i]];
[self addSubview:unit];
[self.units addObject:unit];
}
}
}
唯一有点遗憾的是,我将unitView
存储在array
中,how
和when
,让array
释放掉多余的unitView
三,紧接着就是如何实现‘显示更多’和‘隐藏更多’,
1,我知道tableView
有一个方法- (void)reloadRowAtIndexPath:(NSIndexPath *)indexPath withRowAnimation:(UITableViewRowAnimation)animation;
可以加载指定的行;需要注意到的是这个reload
,并不是复用这个cell
,而是将旧的cell移除,新new一个cell;之前老是要点击两次,也就是这个原因了,方法的英文解释也有说明,只怪当时没注意到;
2,鉴于第一条,我就着重改变下现有tableView
的数据data
了,于是我在上面提到的layout
类中,添加了一个属性,BOOL hidenMore
用来告诉我们是否显示2个以上的副评论,并重新计算了指定的几个height;
3,鉴于第二条我又遇到了几个问题:
1>如何监听基本数据类型;我在方法中执行下面的方法,可惜并没有效果:
这里可以重写setter和getter方法来实现监听:
- (void)setAge:(NSInteger)age{
[self willChangeValueForKey:@"age"];
NSValue *value = [NSValue value:&age withObjCType:@encode(NSInteger)];
objc_setAssociatedObject(self, _cmd, value, OBJC_ASSOCIATION_RETAIN);
[self didChangeValueForKey:@"age"];
}
- (NSInteger)age{
//不明白这里为什么可以使用{0}
NSInteger result = {0};
NSValue *value = objc_getAssociatedObject(self, @selector(setAge:));
[value getValue:&result];
return result;
}
- (void)setCommentLayout:(LTYYCommentLayout *)commentLayout{
// if (_commentLayout != commentLayout && _commentLayout) {
// [_commentLayout removeObserver:self forKeyPath:@"hideMore"];
// }
_commentLayout = commentLayout;
self.subHeights = commentLayout.subComHeights;
self.replyArray = commentLayout.model.replyData;
self.hideMore = commentLayout.hidenMore;
//监听commentLayout的hidemore变化
// [_commentLayout addObserver:self forKeyPath:@"hideMore" options:NSKeyValueObservingOptionNew context:nil];
}
//- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
//
// if ([keyPath isEqualToString:@"hideMore"]) {
// self.hideMore = [object boolValue];
// }
//}
//- (void)dealloc{
// [self.commentLayout removeObserver:self forKeyPath:@"hideMore"];
//}
2>接着1,我在dealloc
注销监听的时候,在界面来回切换,崩溃,cxx
什么的,这里有篇孙源的文章:ARC下dealloc过程及.cxx_destruct的探究
今天先写这点,后续我再看看补充些,