您的位置:首页 > 移动开发 > IOS开发

EasyIOS中AutoLayoutCell加载动态图片的问题

2015-03-12 17:06 337 查看
EasyIOS框架中 AutoLayoutCell  确实是很好用的 。

今天在使用AutoLayoutCell完善一个项目的时候遇到一个问题,当cell在加载通过网络数据请求到的图片的时候,该如何给渲染该图片的UIImageView添加约束。

理论上讲大家都懂:在cell重用的时候,移除UIImageView上旧的约束,添加新约束。理论当然是对的。

先大概讲下我用来测试这个想法用到的案例:

首先,用EasyIOS创建一个项目,自定义一个Scene,里面添加一个tableView,这个tableView当然是EasyIOS里面的ALTableView类型。然后自定义Cell,Cell的模型如下

#import <UIKit/UIKit.h>

@interface CommentCell : UITableViewCell
@property(strong,nonatomic)UIImageView *avator;//这个就是用来显示动态图片的UIImageView
@property(strong,nonatomic)UILabel *nicknameLabel;
@property(strong,nonatomic)UILabel *timeLabel;
@property(strong,nonatomic)UILabel *contentLabel;

- (void)setViewLayout;
@end

//
//  CommentCell.m
//  ledaibao.ios
//
//  Created by 王宏 on 15/2/9.
//  Copyright (c) 2015年 ledaibao. All rights reserved.
//

#import "CommentCell.h"

@implementation CommentCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
[self setBackgroundColor:[UIColor flatWhiteColor]];
_avator = [UIImageView new];
_avator.contentMode = UIViewContentModeScaleAspectFill;
_avator.layer.cornerRadius = 10;
_avator.layer.masksToBounds = YES;
_avator.clipsToBounds = YES;
[self.contentView addSubview:_avator];

_nicknameLabel = [UILabel new];
[_nicknameLabel setFont:[UIFont systemFontOfSize:10.0f]];
[_nicknameLabel setTextColor:[UIColor colorWithRed:0.000 green:0.502 blue:1.000 alpha:0.570]];
[self.contentView addSubview:_nicknameLabel];

_timeLabel = [UILabel new];
[_timeLabel setFont:[UIFont systemFontOfSize:10.0f]];
[_timeLabel setTextColor:[UIColor lightGrayColor]];
[_timeLabel setNumberOfLines:1];
[self.contentView addSubview:_timeLabel];

UIView *line = [[UIView alloc]init];
[self.contentView addSubview:line];
[line setBackgroundColor:[UIColor colorWithWhite:0.767 alpha:0.440]];
[line alignLeading:@"20" trailing:@"-20" toView:line.superview];
[line constrainHeight:@"1"];
[line alignBottomEdgeWithView:line.superview predicate:@"-1"];

_contentLabel = [UILabel new];
[_contentLabel setFont:[UIFont systemFontOfSize:13.0f]];
[_contentLabel setTextColor:[UIColor blackColor]];
[_contentLabel setNumberOfLines:0];
[self.contentView addSubview:_contentLabel];

[self setViewLayout];

}
return self;
}

- (void)setViewLayout
{
//[_avator constrainWidth:@"20" height:@"20@999"];
[_avator constrainWidth:@"20"];
[_avator alignTop:@"10" leading:@"20" toView:_avator.superview];

[_nicknameLabel alignBottomEdgeWithView:_avator predicate:nil];
[_nicknameLabel constrainLeadingSpaceToView:_avator predicate:@"10"];
[_nicknameLabel constrainHeight:@"20"];

[_timeLabel alignBottomEdgeWithView:_avator predicate:nil];
[_timeLabel alignTrailingEdgeWithView:_timeLabel.superview predicate:@"-20"];
[_timeLabel constrainHeight:@"20"];

[_contentLabel constrainTopSpaceToView:_avator predicate:@"10"];
[_contentLabel alignLeading:@"20" trailing:@"-20" toView:_contentLabel.superview];
[_contentLabel alignBottomEdgeWithView:_contentLabel.superview predicate:@"-10"];
}

-(void)prepareForReuse
{
[super prepareForReuse];
//    NSArray *constraints = self.avator.constraints;
//      NSLog(@"111constraints:%@",constraints);
//    for(NSLayoutConstraint *l in constraints)
//    {
//        if(l.priority == 999)
//        {
//            [_avator removeConstraint:l];
//            NSLog(@"111111:%@",_avator.constraints);
//        }
//
//    }
}

@end
.m文件这样已经相当详细了,看- (void)prepareForReuse里面的注释掉的代码,移除旧的约束,然后在cell生成的时候,添加新约束,理论上是没有问题的。但是,关键是这个但是,测试的时候 模拟器显示的时候,cell的高度明显不够  ,看图


下面贴一下我生成cell的过程,

- (void)tableView:(UITableView *)tableView configureCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
CommentCell *commentCell = (CommentCell *)cell;
Comment *comment = [self.commentSceneModel.commentList.commentArray objectAtIndex:indexPath.row];
[commentCell.avator sd_setImageWithURL:[NSURL URLWithString:comment.avator] placeholderImage:[UIImage imageNamed:@"avator"]];

NSArray *heightArray = @[@"30",@"40",@"150",@"60",@"10",@"120",@"55",@"14",@"88",@"168"];

NSString *heightString = [NSString stringWithFormat:@"%@@999",[heightArray objectAtIndex:indexPath.row]];

//    NSArray *constraints = commentCell.avator.constraints;
//    for(NSLayoutConstraint *l in constraints)
//    {
//        if(l.priority == 999)
//        {
//            [commentCell.avator removeConstraint:l];
//        }
//
//    }
[commentCell.avator constrainHeight:heightString];
NSLog(@"111111:%@",commentCell.avator.constraints);

[commentCell.contentLabel setText:comment.content];
[commentCell.nicknameLabel setText:comment.nickname];
NSString *timestamp = [TimeFormat timestamp:comment.createTime];
[commentCell.timeLabel setText:timestamp];
}


为了起到测试效果,我将avator定宽,高度安排数组里面那些高度来模拟动态数据。理论上是ok的 ,但是  问题出在哪里呢,研究了一下午,掰开EasyIOS源码,

找到ALTableViewCellFactory这个文件,找到这里


你发现了什么,是的  EasyIOS框架的ALTableViewCellFactory在计算高度的时候先渲染数据再计算高度,它计算高度的时候自始至终只用了一个cell,所以导致一个问题:在我第一次添加动态图片的约束的时候这个约束存在,第二次计算高度的时候,又添加了一个新的约束条件,而老的约束依然存在,因为计算高度的时候,并没有执行cell的回收方法,所以在prepareForReuse里面去掉旧的约束是不对的,虽然产生的cell是可以用的 但是,计算出来的高度有问题。所以只能在渲染cell内容的时候 ,先判断cell中avator的旧的约束将其删除,后添加新约束,每次都是如此.这样的话:第一,在计算cell高度的时候,能保证cell的avator没有旧约束的干扰,正确的计算cell的高度。第二,生成cell的时候,当cell属于回收cell,可以省略prepareForReuse中对于旧约束的判断,直接写在cell渲染阶段,保证cell约束的完整性.

4000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息