美文网首页iOS学习开发IOS
UITableViewCell重用机制详解

UITableViewCell重用机制详解

作者: 天蓝色的海岸 | 来源:发表于2016-04-07 14:53 被阅读685次

    最近在UItableViewCell的缓冲机制,相信很多开发者都已经清楚,假设手机屏幕一屏有6个cell,当再向上滑动的时候还会再创建一个,当第一个完全消失的时候,这时候再向上滑动的时候就会从缓冲池中找到类型相同的cell。这样就不用重复创建cell了。估计也有不少人遇到过当每个cell所要展示的内容不相同时,被复用折磨的困扰---遮盖原内容。下面我就介绍我的做法

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

    {

    WDSChatTableViewCell *cell = nil;

    // 先获取消息模型

    EMMessage *message = self.dataSources [indexPath.row];

    if ([message.from isEqualToString:self.buddy.username]) {

    // 接收方

    cell = [tableView dequeueReusableCellWithIdentifier:ReceiveCell];

    if (cell==nil)

    {

    cell = [[[NSBundle mainBundle]loadNibNamed:@"WDSChatTableViewCell" owner:self options:nil]lastObject];

    }

    }else{

    // 发送

    cell = [tableView dequeueReusableCellWithIdentifier:SendCell];

    if (cell==nil)

    {

    cell = [[[NSBundle mainBundle]loadNibNamed:@"WDSChatTableViewCell" owner:self options:nil]lastObject];

    }

    }

    //    cell.messaLabel.text = self.dataSources[indexPath.row];

    // 显示内容

    /**

    from wo to ta

    */

    cell.message = message;

    return cell;

    }

    先声明一下我写的demo是模仿环信的

    #import "WDSChatTableViewCell.h"

    #import "EMCDDeviceManager.h"

    #import "WDSAudioPlayTool.h"

    @interface WDSChatTableViewCell()

    @property (nonatomic, strong)UIImageView *chatImageView;

    @end

    @implementation WDSChatTableViewCell

    -(UIImageView *)chatImageView

    {

    if (!_chatImageView) {

    _chatImageView = [[UIImageView alloc]init];

    }

    return _chatImageView;

    }

    - (void)awakeFromNib

    {

    // 此方法可以做初始化

    //1.给label 添加敲击手势

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(messageLabTap:)];

    [self.messaLabel addGestureRecognizer:tap];

    }

    #pragma mark--声音点击的时候触发的方法

    - (void)messageLabTap:(UITapGestureRecognizer *)tap

    {

    // 只有当前的类型为语音的时候才需要播放

    // 获取语音的消息体

    id body = self.message.messageBodies[0];

    if ([body isKindOfClass:[EMVoiceMessageBody class]]) {

    NSLog(@"播放语音");

    BOOL receiver = [self.reuseIdentifier isEqualToString:ReceiveCell];

    [WDSAudioPlayTool playWithMessage:self.message magLabel:self.messaLabel receiver:receiver];

    }

    }

    - (void)setMessage:(EMMessage *)message

    {

    [self.chatImageView removeFromSuperview];

    // 关键点就在此处,懒加载imageView然后在重用的时候将

    //UIImageView从父视图移除,这样就不会被复用遮盖了

    _message = message;

    id body = message.messageBodies[0];

    if ([body isKindOfClass:[EMTextMessageBody class]]) {

    EMTextMessageBody *textBody = body;

    self.messaLabel.text = textBody.text;

    }else if([body isKindOfClass:[EMVoiceMessageBody class]]){

    self.messaLabel.attributedText = [self voiceAtt];

    }else if ([body isKindOfClass:[EMImageMessageBody class]]){

    [self showImage];

    }else{

    self.messaLabel.text = @"未知的类型";

    }

    }

    #pragma mark--显示图片

    - (void)showImage

    {

    if ([self.reuseIdentifier isEqualToString:SendCell]) {

    //    获取图片消息体

    EMImageMessageBody *imgBody = self.message.messageBodies[0];

    CGRect thumbnailFrm = (CGRect){0,0,imgBody.thumbnailSize};

    NSLog(@"%f",thumbnailFrm.size.height);

    // 设置Label的尺寸足够显示UIimageView

    NSTextAttachment *imgAttach = [[NSTextAttachment alloc]init];

    imgAttach.bounds =thumbnailFrm;

    // 占位思想

    NSAttributedString *imgAtt = [NSAttributedString attributedStringWithAttachment:imgAttach];

    self.messaLabel.attributedText = imgAtt;

    //1.首先要在cell里面添加一个UIImageView

    [self.messaLabel addSubview:self.chatImageView];

    // 2.设置图片控件为缩略图的尺寸

    self.chatImageView.frame = thumbnailFrm;

    self.chatImageView.backgroundColor = [UIColor redColor];

    //    3.下载图片

    NSLog(@"%@",imgBody.thumbnailLocalPath);

    NSLog(@"%@",imgBody.thumbnailRemotePath);

    // 如果本地图片存在,直接从本地显示图片

    NSFileManager *manager = [NSFileManager defaultManager];

    UIImage *placeImg = [UIImage imageNamed:@"downloading"];

    if ([manager fileExistsAtPath:imgBody.thumbnailLocalPath]) {

    [self.chatImageView sd_setImageWithURL:[NSURL fileURLWithPath:imgBody.thumbnailLocalPath]placeholderImage:placeImg];

    }else

    {

    // 如果本地图片不存  从网络加载图片

    [self.chatImageView sd_setImageWithURL:[NSURL URLWithString:imgBody.thumbnailRemotePath]placeholderImage:placeImg];

    }

    }else

    {

    //    获取图片消息体

    EMImageMessageBody *imgBody = self.message.messageBodies[0];

    CGRect thumbnailFrm = (CGRect){0,0,imgBody.thumbnailSize};

    NSLog(@"%f",thumbnailFrm.size.height);

    // 设置Label的尺寸足够显示UIimageView

    NSTextAttachment *imgAttach = [[NSTextAttachment alloc]init];

    imgAttach.bounds =thumbnailFrm;

    // 占位思想

    NSAttributedString *imgAtt = [NSAttributedString attributedStringWithAttachment:imgAttach];

    self.messaLabel.attributedText = imgAtt;

    //1.首先要在cell里面添加一个UIImageView

    [self.messaLabel addSubview:self.chatImageView];

    // 2.设置图片控件为缩略图的尺寸

    self.chatImageView.frame = thumbnailFrm;

    self.chatImageView.backgroundColor = [UIColor redColor];

    //    3.下载图片

    NSLog(@"%@",imgBody.thumbnailLocalPath);

    NSLog(@"%@",imgBody.thumbnailRemotePath);

    // 如果本地图片存在,直接从本地显示图片

    NSFileManager *manager = [NSFileManager defaultManager];

    UIImage *placeImg = [UIImage imageNamed:@"downloading"];

    if ([manager fileExistsAtPath:imgBody.thumbnailLocalPath]) {

    [self.chatImageView sd_setImageWithURL:[NSURL fileURLWithPath:imgBody.thumbnailLocalPath]placeholderImage:placeImg];

    }else

    {

    // 如果本地图片不存  从网络加载图片

    [self.chatImageView sd_setImageWithURL:[NSURL URLWithString:imgBody.thumbnailRemotePath]placeholderImage:placeImg];

    }

    }

    }

    #pragma mark--返回语音的副文本

    - (NSAttributedString *)voiceAtt{

    // 创建一个可变的副文本

    NSMutableAttributedString *voiceAttM = [[NSMutableAttributedString alloc]init];

    if ([self.reuseIdentifier isEqualToString:ReceiveCell]) {

    // 接收方  ,富文本 = 图片+时间

    UIImage *receiverImg = [UIImage imageNamed:@"chat_receiver_audio_playing_full"];

    // 创建一个图片的附件

    NSTextAttachment *imgAttachment = [[NSTextAttachment alloc]init];

    imgAttachment.image = receiverImg;

    imgAttachment.bounds = CGRectMake(0, -7, 30, 30);

    // 图片副文本

    NSAttributedString *imgAtt = [NSMutableAttributedString attributedStringWithAttachment:imgAttachment];

    [voiceAttM appendAttributedString:imgAtt];

    // 创建时间的副文本

    // 获取时间

    EMVoiceMessageBody *voiceBody = self.message.messageBodies[0];

    NSInteger duration = voiceBody.duration;

    NSString *timeStr = [NSString stringWithFormat:@"%d",duration];

    NSAttributedString *timeAtt = [[NSAttributedString alloc]initWithString:timeStr];

    [voiceAttM appendAttributedString:timeAtt];

    }else

    {

    // 发送方:副文本 = 时间+图片

    // 创建时间的副文本

    // 获取时间

    EMVoiceMessageBody *voiceBody = self.message.messageBodies[0];

    NSInteger duration = voiceBody.duration;

    NSString *timeStr = [NSString stringWithFormat:@"%d",duration];

    NSAttributedString *timeAtt = [[NSAttributedString alloc]initWithString:timeStr];

    [voiceAttM appendAttributedString:timeAtt];

    UIImage *receiverImg = [UIImage imageNamed:@"chat_sender_audio_playing_full"];

    // 创建一个图片的附件

    NSTextAttachment *imgAttachment = [[NSTextAttachment alloc]init];

    imgAttachment.image = receiverImg;

    imgAttachment.bounds = CGRectMake(0, -7, 30, 30);

    // 图片副文本

    NSAttributedString *imgAtt = [NSMutableAttributedString attributedStringWithAttachment:imgAttachment];

    [voiceAttM appendAttributedString:imgAtt];

    }

    return [voiceAttM copy];

    }

    // 返回cell的高度

    - (CGFloat)cellHeight:(EMMessage *)message

    {

    [self setNeedsLayout];

    [self layoutIfNeeded];

    id body = message.messageBodies[0];

    if ([body isKindOfClass:[EMTextMessageBody class]]) {

    CGRect tmpRect = [self.messaLabel.text boundingRectWithSize:CGSizeMake(242, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:17],NSFontAttributeName, nil] context:nil];

    return 5+10+tmpRect.size.height+10+5;

    }else if([body isKindOfClass:[EMVoiceMessageBody class]]){

    CGRect tmpRect = [self.messaLabel.text boundingRectWithSize:CGSizeMake(242, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:17],NSFontAttributeName, nil] context:nil];

    return 5+10+tmpRect.size.height+10+5;

    }else if ([body isKindOfClass:[EMImageMessageBody class]]){

    EMImageMessageBody *imgBody = body;

    CGRect thumbnailFrm = (CGRect){0,0,imgBody.thumbnailSize};

    CGRect tmpRect2= [self.messaLabel.attributedText boundingRectWithSize:thumbnailFrm.size options:NSStringDrawingUsesLineFragmentOrigin context:nil];

    return 5+10+tmpRect2.size.height+10+5;

    }else{

    return 0;

    }

    //1.重新布局子控件

    //    [super layoutIfNeeded];

    //    [self setNeedsLayout];

    //    [self layoutIfNeeded];

    //    [self layoutSubviews];

    //    NSLog(@"%f",self.messaLabel.bounds.size.height);

    ////    NSLog(@"%@",self.messaLabel.text);

    //

    //    EMImageMessageBody *imgBody = self.message.messageBodies[0];

    //    CGRect thumbnailFrm = (CGRect){0,0,imgBody.thumbnailSize};

    //  CGRect tmpRect2= [self.messaLabel.attributedText boundingRectWithSize:thumbnailFrm.size options:NSStringDrawingUsesLineFragmentOrigin context:nil];

    //

    //    CGRect tmpRect = [self.messaLabel.text boundingRectWithSize:CGSizeMake(242, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:17],NSFontAttributeName, nil] context:nil];

    ////    CGRect tmpRect2 = self.messaLabel.attributedText

    ////  CGSize temp = [self.messaLabel.text sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:CGSizeMake(242, MAXFLOAT)];

    ////    CGSize temp = [self.messaLabel.text sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:17],NSFontAttributeName,CGSizeMake(242, MAXFLOAT), nil]];

    //

    ////    NSLog(@"----%f",tmpRect.size.height);

    ////    self.messaLabel.bounds.size.height

    ////    return 5+10+tmpRect.size.height+10+5;

    //    return 5+10+tmpRect2.size.height+10+5;

    //    return 5+10+self.messaLabel.bounds.size.height+10+5;

    }

    另外一点在计算不同cell高度的时候我选择了不同类型的cell不同的处理,不过用[self.messaLabel.attributedText boundingRectWithSize:thumbnailFrm.size options:NSStringDrawingUsesLineFragmentOrigin context:nil];这个方法还是有缺陷的,它的大小不是原始大小

    //  Xiaoqiuhuanxin

    //

    相关文章

      网友评论

        本文标题:UITableViewCell重用机制详解

        本文链接:https://www.haomeiwen.com/subject/kenmlttx.html