功能实现一

最近有个界面需求长这样;

功能实现一_第1张图片
屏幕快照 2017-03-22 11.10.31.png

刚开始拿到这个界面的时候,我就懵逼了,这咋整啊;得,再怎么懵逼也得继续啊;

一,思路:

整体来说,先给他扣个tableView吧,剩下的也就是怎么处理tableViewCell了;再细看,整个cell有两部分组成,一部分是主评论,一部分是副评论;主评论还好说,3个label,1个imageView;副评论就不行了,这副评论还是变化的,这可怎么办?

1,再细看,副评论也就是固定样式的view的个数;想想自适应高度是不行了,只能看看如何得到高度,然后根据得到的高度来处理了;

2,副评论如何放在整个cell上面;

二,看来要获得整个cell的高度,少不了计算了,那么如何计算,以及如何让计算最可能的优化;之前是了解了下YYKit框架,我想也许我能在子线程中计算整个我需要的height,再有一点,YYkit使用的是轻量级的layer,由于整个项目使用的masonry,并且我也不大想每个都计算,于是通过在拿到数据model的时候,我顺便计算了我想要的几个label的高度,至于其他的就是美工给的固定尺寸了;

解1: 这里我在子线程中初始化一个带有modellayout类,用来计算了我所需要的所有高度的数据;

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;这样是可以实现,这个又有个问题了,我不想频繁的initaddremove;那么如何实现unitView的复用呢?想想可以把用到的unitView存起来,下次只要刷新label.textimageView.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 *)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中,howwhen,让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 *)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的探究

今天先写这点,后续我再看看补充些,

你可能感兴趣的:(功能实现一)