iOS开发项目篇—46时间和来源的处理(cell的复用问题)

iOS开发项目篇—46时间和来源的处理(cell的复用问题)
一、简单说明

1.存在的问题:

           

2.问题描述:

刷新微博界面后,展示的最新的微博数据时间显示为“刚刚”,在项目中对时间进行设计的时候,如果是在1分钟之内发表的,那么显示为“刚刚”。查看后面的微博数据后,回过头来(1分钟已经过去了),此时之前显示为“刚刚”的微博,应该显示XX分钟以前,确实显示了,但是时间的frame不正确(此时的frame=="刚刚"两个字的frame)。

提示:cell的复用问题,为了提升性能节省内存,cell在设计的时候是只创建显示到眼前【界面】上的cell,当滚动的时候,复用之前创建的cell。

3.问题出在了哪里?

根据展示的效果,时间从“刚刚”--》“XX分钟之前”,可以知道代码设计部分已经完成了实时对“时间”数据进行更新的功能(总是拿微博发表的时间和当前的时间进行比较,再显示提示的时间信息),但是frame却没有被再次计算,还是之前的数值,也就是说在整个过程中,时间的显示【“刚刚”  “XX分钟前” “一小时前”】等是不断刷新计算的,而显示时间的frame在程序中只被设置了一个初值,之后并没有同步的进行设置。

4.简单说明:显示时间的label的宽度永远是“刚刚”这两个汉字的宽度。

 

二、解决cell的复用产生的问题

显示时间的label的frame不能只计算一次,也应该要实时的进行更新。

1.在原创微博frame中再计算时间和来源的frame没有意义,删除相关代码。

提示:因为微博来源的frame和时间label的frame有直接的关系,所以连带着也应该计算来源的frame。

YYStatusOriginalFrame.h文件

 1 //
 2 //  YYStatusOriginalFrame.h
 3 //
 4 
 5 #import <Foundation/Foundation.h>
 6 
 7 @class YYStatusModel;
 8 @interface YYStatusOriginalFrame : NSObject
 9 /**
10  *  微博数据模型
11  */
12 @property(nonatomic,strong)YYStatusModel *status;
13 
14 /** 昵称 */
15 @property (nonatomic, assign) CGRect nameFrame;
16 /** 正文 */
17 @property (nonatomic, assign) CGRect textFrame;
18 ///** 来源 */
19 //@property (nonatomic, assign) CGRect sourceFrame;
20 ///** 时间 */
21 //@property (nonatomic, assign) CGRect timeFrame;
22 /** 头像 */
23 @property (nonatomic, assign) CGRect iconFrame;
24 /** 会员图标 */
25 @property (nonatomic, assign) CGRect vipViewFrame;
26 
27 /** 自己的frame */
28 @property (nonatomic, assign) CGRect frame;
29 @end

2.需要时刻根据现在的时间计算,显示时间和微博来源的label的frame

YYStatusOriginal.m文件

  1 //
  2 //  YYStatusOriginal.m
  3 //
  4 
  5 #import "YYStatusOriginalView.h"
  6 #import "YYStatusOriginalFrame.h"
  7 #import "YYUserModel.h"
  8 #include "YYStatusModel.h"
  9 #import "UIImageView+WebCache.h"
 10 
 11 @interface YYStatusOriginalView ()
 12 /**
 13  *  头像
 14  */
 15 @property(nonatomic,weak)UIImageView *iconView;
 16 /**
 17  *  昵称
 18  */
 19 @property(nonatomic,weak)UILabel  *nameLabel;
 20 /**
 21  *  微博的正文
 22  */
 23 @property(nonatomic,weak)UILabel *textLabel;
 24 /**
 25  *  时间
 26  */
 27 @property(nonatomic,weak)UILabel *timeLabel;
 28 /**
 29  *  来源
 30  */
 31 @property(nonatomic,weak)UILabel *sourceLabel;
 32 /**
 33  *  会员图标
 34  */
 35 @property(nonatomic,weak)UIImageView *vipView;
 36 
 37 @end
 38 @implementation YYStatusOriginalView
 39 
 40 - (id)initWithFrame:(CGRect)frame
 41 {
 42     self = [super initWithFrame:frame];
 43     if (self) {
 44         //初始化子控件
 45         //1.头像
 46         UIImageView *iconView=[[UIImageView alloc]init];
 47         [self addSubview:iconView];
 48         self.iconView=iconView;
 49         
 50         //2.昵称
 51         UILabel *nameLabel=[[UILabel alloc]init];
 52         nameLabel.font=YYStatusOrginalNameFont;
 53         [self addSubview:nameLabel];
 54         self.nameLabel=nameLabel;
 55         
 56         //3.正文
 57         UILabel *textLabel=[[UILabel alloc]init];
 58         textLabel.font=YYStatusOrginalTextFont;
 59         textLabel.numberOfLines=0;
 60         [self addSubview:textLabel];
 61         self.textLabel=textLabel;
 62         
 63         //4.时间
 64         UILabel *timeLabel=[[UILabel alloc]init];
 65         timeLabel.font=YYStatusOrginalTimeFont;
 66         timeLabel.textColor=[UIColor orangeColor];
 67         [self addSubview:timeLabel];
 68         self.timeLabel=timeLabel;
 69         
 70         //5.来源
 71         UILabel *sourceLabel=[[UILabel alloc]init];
 72         sourceLabel.font=YYStatusOrginalSourceFont;
 73         sourceLabel.textColor=[UIColor lightGrayColor];
 74         [self addSubview:sourceLabel];
 75         self.sourceLabel=sourceLabel;
 76         
 77         //6.会员图标
 78         UIImageView *vipView=[[UIImageView alloc]init];
 79         //会员图标应该设置保持原来的尺寸,垂直居中
 80         vipView.contentMode=UIViewContentModeCenter;
 81         [self addSubview:vipView];
 82         self.vipView=vipView;
 83         
 84     }
 85     return self;
 86 }
 87 
 88 -(void)setOriginalFrame:(YYStatusOriginalFrame *)originalFrame
 89 {
 90     _originalFrame=originalFrame;
 91     
 92     //设置自己的frame
 93     self.frame=originalFrame.frame;
 94     
 95     //取出模型数据
 96     YYStatusModel *status=originalFrame.status;
 97     
 98     //设置头像的frame
 99     [self.iconView setImageWithURL:[NSURL URLWithString:status.user.profile_image_url] placeholderImage:[UIImage imageWithName:@"avatar_default_small"]];
100     self.iconView.frame=originalFrame.iconFrame;
101     
102     //设置昵称的frame
103     self.nameLabel.text=status.user.name;
104     //注意循环利用的问题
105     if (status.user.isVip) {
106         self.nameLabel.textColor=[UIColor orangeColor];
107         self.vipView.hidden=NO;
108         self.vipView.frame=originalFrame.vipViewFrame;
109         self.vipView.image=[UIImage imageWithName:[NSString stringWithFormat:@"common_icon_membership_level%d",status.user.mbrank]];
110     }else
111     {
112         self.nameLabel.textColor=[UIColor blackColor];
113         self.vipView.hidden=YES;
114     }
115     self.nameLabel.frame=originalFrame.nameFrame;
116     
117     //设置正文的frame
118     self.textLabel.text=status.text;
119     self.textLabel.frame=originalFrame.textFrame;
120   
121 #warning 需要时刻根据现在的时间计算,显示时间和微博来源的label的frame
122     //设置时间的frame
123     NSString *timeStr=status.created_at;
124     self.timeLabel.text=timeStr;
125     
126     CGFloat timeX=CGRectGetMinX(self.nameLabel.frame);
127     CGFloat timeY=CGRectGetMaxY(self.nameLabel.frame)+YYCellStatusInset*0.5;
128     CGSize timeSize=[timeStr sizeWithFont:YYStatusOrginalTimeFont];
129     self.timeLabel.frame=(CGRect){{timeX,timeY},timeSize};
130     
131     //设置来源的frame
132     self.sourceLabel.text=status.source;
133     
134     CGFloat sourcceX=CGRectGetMaxX( self.timeLabel.frame)+YYCellStatusInset;
135     CGFloat sourcceY=timeY;
136     CGSize sourcceSize=[status.source sizeWithFont:YYStatusOrginalSourceFont];
137     self.sourceLabel.frame=(CGRect){{sourcceX,sourcceY},sourcceSize};
138     
139 }
140 @end

 

3.修复了这个问题的显示效果:

     

4.性能优化处理

  说明:

(1)每次刷新,都需要对时间进行处理,但是微博的来源是固定的,没必要每次刷新的时候就调用一次浪费掉宝贵的内存空间。

(2)且在设置微博来源的时候,是通过截取并拼接字符串这样的方式进行的,而这恰是特别耗时的操作。没必要每次调用self.sourceLabel.text=status.source;的时候都去拼接字符串(这个方法调用非常频繁,每当一个cell进入到视野的时候,都会计算一遍)。

(3)计算时间,每次得出的结果是不一样的。但是计算微博来源,每次截取字符串都是固定的,是一样的。

(4)set方法只会在字典转模型的那一刻调用(因为要把字典属性赋值给模型属性),get方法时刻都在调用。

(5)解决方法:删除get方法,重写一个相应的set方法

YYStatusModel.m文件

  1 //
  2 //  YYStatusModel.m
  3 //
  4 
  5 #import "YYStatusModel.h"
  6 #import "MJExtension.h"
  7 #import "YYPhotoModel.h"
  8 #import "NSDate+MJ.h"
  9 
 10 @implementation YYStatusModel
 11 //+(instancetype)statusModelWithDict:(NSDictionary *)Dict
 12 //{
 13 //    YYStatusModel *model=[[self alloc]init];
 14 //    model.text=Dict[@"text"];
 15 //    
 16 //    model.user=[YYUserModel userModelWithDict:Dict[@"user"]];
 17 //    
 18 //    //嵌套模型
 19 //    NSDictionary *retweetedDict = Dict[@"retweetedDict"];
 20 //    if (retweetedDict) {
 21 //        model.retweeted_status=[YYStatusModel statusModelWithDict:retweetedDict];
 22 //    }
 23 //    return model;
 24 //}
 25 
 26 -(NSDictionary *)objectClassInArray
 27 {
 28       return @{@"pic_urls" : [YYPhotoModel class]};
 29 }
 30 
 31 //重写创建时间的get方法
 32 /**_created_at==Sat Jul 19 15:24:04 +0800 2014*/
 33 -(NSString *)created_at
 34 {
 35 //    _created_at=@"Sat Jul 18 15:24:04 +0800 2014";
 36     NSDateFormatter *fmt=[[NSDateFormatter alloc]init];
 37     //时间格式
 38     fmt.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
 39     //获得尾部发布的具体时间
 40     NSDate *creatDate = [fmt dateFromString:_created_at];
 41     
 42     //判断是否为今年
 43     if (creatDate.isThisYear) {//今年
 44         if (creatDate.isToday) {
 45             //获得微博发布的时间与当前时间的差距
 46             NSDateComponents *cmps=[creatDate deltaWithNow];
 47             if (cmps.hour>=1) {//至少是一个小时之前发布的
 48                 return [NSString stringWithFormat:@"%d小时前",cmps.hour];
 49             }else if(cmps.minute>=1){//1~59分钟之前发布的
 50                 return [NSString stringWithFormat:@"%d分钟前",cmps.minute];
 51             }else{//1分钟内发布的
 52                 return @"刚刚";
 53             }
 54         }else if(creatDate.isYesterday){//昨天发的
 55             fmt.dateFormat=@"昨天 HH:mm";
 56             return [fmt stringFromDate:creatDate];
 57         }else{//至少是前天发布的
 58             fmt.dateFormat=@"MM-dd HH:mm";
 59             return [fmt stringFromDate:creatDate];
 60         }
 61     }else           //  往年
 62     {
 63         fmt.dateFormat=@"yyyy-MM-dd";
 64         return [fmt stringFromDate:creatDate];
 65     }
 66 }
 67 /**_source== <a href="http://app.weibo.com/t/feed/3j6BDx" rel="nofollow">孔明社交管理</a>*/
 68 //所需要的:孔明社交管理
 69 //-(NSString *)source
 70 //{
 71 //    //截取字符串,获得子串
 72 //    //截取的范围
 73 //    NSRange range;
 74 //    //截取的位置:第一个>之后
 75 //    range.location=[_source rangeOfString:@">"].location+1;
 76 //    //截取的长度:第二个<的位置到第一个>之间的长度
 77 //    range.length=[_source rangeOfString:@"</"].location-range.location;
 78 //    
 79 //    //开始截取
 80 //    NSString *subSource=[_source substringWithRange:range];
 81 //    //头部拼接“来自”
 82 //    return [NSString stringWithFormat:@"来自%@",subSource];
 83 //}
 84 
 85 -(void)setSource:(NSString *)source
 86 {
 87     //截取字符串,获得子串
 88     //截取的范围
 89     NSRange range;
 90     //截取的位置:第一个>之后
 91     range.location=[source rangeOfString:@">"].location+1;
 92     //截取的长度:第二个<的位置到第一个>之间的长度
 93     range.length=[source rangeOfString:@"</"].location-range.location;
 94 
 95     //开始截取
 96     NSString *subSource=[source substringWithRange:range];
 97     //头部拼接“来自”
 98     _source = [NSString stringWithFormat:@"来自%@",subSource];
 99 }
100 
101 @end

提示:KVC的本质也是调用set方法。

iOS开发项目篇—46时间和来源的处理(cell的复用问题),,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。