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 //    [email protected]"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的复用问题)

时间: 2024-08-04 15:20:36

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

iOS开发项目篇—45时间和来源处理

iOS开发项目篇—45时间和来源处理 一.时间的处理 1.简单说明 系统返回的时间是欧美通用的时区时间,需要进行处理和调整. 根据微博发送的时间和当前的时间进行比较,显示“刚刚”.“一小时前”.“一天前”等. 时间处理的情况: (1)今年 1)今天 1>1分钟内:刚刚 2>1个小时内:XX分钟前 2)昨天 XX:XX 3)至少是前天发的 07-12 XX:XX (2)非今年 2012-02-11 2.解决思路:重写微博创建时间的get方法,可以把有关时间细节的踔厉隐藏在模型中完成. (1)时间

iOS开发项目篇—47Toolbar工具条

iOS开发项目篇—47Toolbar工具条 一.基本设置 说明:完成微博cell中toolbar的基本设置(转发数.评论数.赞) 实现代码: YYStatusToolbar.m文件 1 // 2 // YYStatusToolbar.m 3 // 4 5 #import "YYStatusToolbar.h" 6 7 @interface YYStatusToolbar () 8 /**用来保存两条竖线*/ 9 @property(nonatomic,strong)NSMutableA

iOS开发项目篇—24字典转模型

iOS开发项目篇—24字典转模型 一.直接使用字典转模型 1.微博数据转模型示意图: 2.字典转模型 查询字段: 新建需要的数据模型: 字典转模型相关的代码: YYUserModel.h文件 1 // 2 // YYUserModel.h 3 // 4 5 #import <Foundation/Foundation.h> 6 7 @interface YYUserModel : NSObject 8 9 /** string 友好显示名称*/ 10 @property(nonatomic,c

iOS开发项目篇—44会员处理

iOS开发项目篇—44会员处理 一.简单说明 查看已经完成的效果: 存在的问题和调整: (1)时间和昵称之间的间距较大,调整*0.5. (2)转发微博的用户昵称和微博正文间距较大,调整(2). (3).微博来源设置为亮灰色 打开微博来源,修改之前存在的一个bug. 设置颜色为亮灰色 (4).设置时间字体为橙色. 上面一系列调整完成之后的显示效果为: 二.会员设置 1.说明 微博的用户分为会员和非会员,而根据是否是会员,用户昵称的颜色也不一样,会员显示为橙色,普通用户显示为黑色. 哪些属性是何用户

iOS开发项目篇—43子控件的细节处理

iOS开发项目篇—43子控件的细节处理 一.升级UI 把之前的UI图片删除,换上新的图片(图片命名一致,规范)没有其他的影响. 删除之后,添加. 替换之后,做一次clear操作. 建议把沙盒中的包删除,删除之后再做一次clear操作. 二.调整转发(模块) 1.设置背景(使用提供的素材图片进行平铺) 为转发微博部分设置背景,考虑到这个部分整体上是一个UIView,可以尝试以下设置. 第一种尝试: 但是这样设置,因为图片是平铺的,所以整个背景会出现线条效果,影响显示,不可行. 第二种尝试: 注意:

iOS开发项目篇—41cell的frame设计

iOS开发项目篇—41cell的frame设计 一.简单说明 1.分层设计 在进行设计的时候,建议先分析整个cell的结构,确定了cell由哪些模块构成之后,再进一步确定每个模块中包含的子控件. 在这个微博的cell中,把这个cell分成两个大的模块.分解结构如下: 1.微博完整内容模块View (1)原创微博view 1)头像imageView 2)自己的昵称label 3)发布的时间label 4)微博来源label 5)微博的正文 (2)转发微博 1)原作者的昵称label 2)转发的微博

iOS开发项目篇—41cell的frame的细节处理

iOS开发项目篇—41cell的frame的细节处理 一.简单说明 在首页控制器中使用自定义的UITableViewcell 代码如下: YYHomeTableViewController.m文件 1 // 2 // YYHomeTableViewController.m 3 // 4 5 #import "YYHomeTableViewController.h" 6 #import "YYOneViewController.h" 7 #import "Y

iOS开发项目篇—36封装微博业务

iOS开发项目篇—36封装微博业务 一.简单说明 1.请求参数面向模型 2.请求结果面向模型 3.对控制器来说应该屏蔽业务细节.不让控制器关心(知道)业务细节,它只需要知道自己在做某个业务 @通过一个专门的业务处理类:处理微博业务细节 说明: 业务:加载新的微博首页数据 实现:给新浪服务器发送一个GET请求 业务:加载更多的首页微博数据 实现1:给新浪服务器发送一个GET请求 实现2:去沙盒中加载以前离线缓存的微博数据  二.实现 1.新建一个微博业务处理类,继承自NSObject 微博业务处理

iOS开发项目篇—34获取用户信息

iOS开发项目篇—34获取用户信息 一.简单说明 需求:获取当前用户的昵称 ,需要获取当前登录用户的个人信息. 查看接口 要求传递的参数 这里要获取的时用户的昵称(所以使用用户id作为参数传入) 二.实现代码 1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 //设置导航栏内容 6 [self setupNavBar]; 7 8 //集成刷新控件 9 [self setupRefresh]; 10 11 //设置用户的昵称为标题 12 [s