献给初学iOS的小盆友们——微博app项目开发之十三微博时间和来源处理
2016-01-28 13:27
399 查看
上节课我们基本把微博的主要数据都给展现出来了,数据也用视图模型给全部打通了。以后再遇到复杂的控件时候,先冷静分析,不要慌,然后划分界面结构,然后添加子控件,计算子控件的位置,如果控件内容由模型决定,就要想到使用MVVM概念,然后把模型转换为视图模型,最后给控件赋值模型视图。但是我们发现上节课的结果有两个地方特别让人不满意,一个是微博时间,一个是微博来源,这节课我们就主要解决这两个问题。
微博来源处理
还有一个就是,我们发现在下拉刷新的时候总是出现同样的内容,才知道我们把LoadMoreStatus方法写错了,我们每次要取到数组里最后一个微博的idstr才能加载更旧的微博。更改代码如下:
现在我们开始处理时间,如果我们把服务器给我们的时间打印出来会是这样的效果:
但是我们想要的日期格式是要跟当前的时期做对比然后,不同的时间间隔会有不同的格式:
我们每次都在在YGOriginalView的setUpData给时间的timeView赋值,所以我们想在赋值即将发生之前,让微博的creat_at属性与系统时间当前做对比,对比的结果就如上面所列举的一样。所以我们要重写creat_at的get方法,把对比后的结果赋值给timeView。
所以我们就决定在YGStatus.m内重写getCreat_at方法,代码如下:
这里我们使用了MJ大神的一个分类NSDate+MJ,他给我们写好了对比对比系统时间的方法。此时你应该很高兴吧:这代码太简单了吧,没点挑战性。但是你跑下代码试试,傻眼了吧,有没有发现下面的错误:
![](http://img.blog.csdn.net/20160128114039187)
时间的frame不是已经设计好了么,为什么这里面又不能完全显示字符了,而且我们也用了sizeWithFont功能啊。问题在哪里呢?请思考思考再往下看。
第一 你要知道当我们在getCreat_at方法内添加打印时间代码,
第二 启动项目后,第一条微博时间应该显示的是刚刚。然后隔一两分钟,当我们在上下滑动tableView的时候,cell会被重用,这个都知道吧。重用cell的时候,又会调用tableView的代理方法吧,在代理方法内,又会重新调用cell的setStatusFrame方法,setStatusFrame方法内又会给originalView的statusFrame赋值,在YGOriginalView的setStatusFrame就又会给微博的timeView赋值吧,这就又一次调用了creat_at 的get方法了,但是这一次取出的值是根当下的系统时间做对比的,所以当你隔了一段时间再次调用get方法,显示的就不是“刚刚”了,而是“一分钟或者几分钟之前”。如果你再把“XX分钟之前”赋值给frame已经固定的timeView的话,那肯定就显示不正常啦。那怎么办呢???
第三 现在我们就要考虑,怎么让它显示正常呢,很简单,改变一下frame大小不就OK啦。我们把计算timeFrame的步骤放到YGOrginalView.m内的setUpFrame内即可,因为正好这个方法就刚刚在setUpData之前,我们更新了frame大小,就可以正常显示内容了。代码如下:
因为来源的frame是依赖于时间的frame的,所以这里一并把来源的frame也给重新计算了。
这里最主要的就是获取“>”和“<”的角标,通过角标来截取source内的字符串。
最后别忘了改变sourceView的文字颜色为浅灰色。
好啦,这节课就到这里吧,好好理解我们刚才是怎么处理时间显示问题的,会对你理解tableView的重用有很大帮助。
本节内容
微博时间处理微博来源处理
本节资料
第十三节代码资料13.1微博时间处理
在处理时间之前,我们首先处理两个小问题,一个就是把tableView的分割线去掉。在YGHomeViewController内的viewDidLoad方法内添加如下代码:[code]// 取消分割线 self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
还有一个就是,我们发现在下拉刷新的时候总是出现同样的内容,才知道我们把LoadMoreStatus方法写错了,我们每次要取到数组里最后一个微博的idstr才能加载更旧的微博。更改代码如下:
[code]YGStatus *s = [[self.statuseFrames lastObject] status];
现在我们开始处理时间,如果我们把服务器给我们的时间打印出来会是这样的效果:
[code]Thu Jan 28 11:14:19 +0800 2016
但是我们想要的日期格式是要跟当前的时期做对比然后,不同的时间间隔会有不同的格式:
[code]if 今年 if 今天 if 小于等于一分钟 就显示“刚刚” if 大于一分钟小于一分钟 就显示“xx分钟之前” if 大于一小时小于24小时 就显示“xx小时之前” if 昨天 就显示“昨天 08:20” if 2天之前 就显示“02-14 08:20” if 非今年 就显示“2014-02-14 08:20”
我们每次都在在YGOriginalView的setUpData给时间的timeView赋值,所以我们想在赋值即将发生之前,让微博的creat_at属性与系统时间当前做对比,对比的结果就如上面所列举的一样。所以我们要重写creat_at的get方法,把对比后的结果赋值给timeView。
所以我们就决定在YGStatus.m内重写getCreat_at方法,代码如下:
[code]- (NSString *)created_at { // 字符串转换NSDate // 日期格式字符串 NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; fmt.dateFormat = @"EEE MMM d HH:mm:ss Z yyyy"; NSDate *created_at = [fmt dateFromString:_created_at]; if ([created_at isThisYear]) { // 今年 if ([created_at isToday]) { // 今天 // 计算跟当前时间差距 NSDateComponents *cmp = [created_at deltaWithNow]; if (cmp.hour >= 1) { return [NSString stringWithFormat:@"%ld小时之前",cmp.hour]; }else if (cmp.minute > 1){ return [NSString stringWithFormat:@"%ld分钟之前",cmp.minute]; }else{ return @"刚刚"; } }else if ([created_at isYesterday]){ // 昨天 fmt.dateFormat = @"昨天 HH:mm"; return [fmt stringFromDate:created_at]; }else{ // 前天 fmt.dateFormat = @"MM-dd HH:mm"; return [fmt stringFromDate:created_at]; } }else{ // 不是今年 fmt.dateFormat = @"yyyy-MM-dd HH:mm"; return [fmt stringFromDate:created_at]; } return _created_at; }
这里我们使用了MJ大神的一个分类NSDate+MJ,他给我们写好了对比对比系统时间的方法。此时你应该很高兴吧:这代码太简单了吧,没点挑战性。但是你跑下代码试试,傻眼了吧,有没有发现下面的错误:
时间的frame不是已经设计好了么,为什么这里面又不能完全显示字符了,而且我们也用了sizeWithFont功能啊。问题在哪里呢?请思考思考再往下看。
第一 你要知道当我们在getCreat_at方法内添加打印时间代码,
NSLog(@"%@",_created_at);然后在tableView的代理内也添加打印代码
NSLog(@"%ld",(long)indexPath.row);最后运行项目,可以发现creat_at 首先被印了20次,然后才打印tableView的行号。这是因为我们在得到模型后,在模型转视图模型的时候用到了getCreat_at方法,所以它首先被打印了20次。然后每个微博的视图模型的timeFrame就根据这次获得的时间就计算好了,并且已经固定,后面没有再做更改。(记住模型没有再更改哦,一定记住了。)
第二 启动项目后,第一条微博时间应该显示的是刚刚。然后隔一两分钟,当我们在上下滑动tableView的时候,cell会被重用,这个都知道吧。重用cell的时候,又会调用tableView的代理方法吧,在代理方法内,又会重新调用cell的setStatusFrame方法,setStatusFrame方法内又会给originalView的statusFrame赋值,在YGOriginalView的setStatusFrame就又会给微博的timeView赋值吧,这就又一次调用了creat_at 的get方法了,但是这一次取出的值是根当下的系统时间做对比的,所以当你隔了一段时间再次调用get方法,显示的就不是“刚刚”了,而是“一分钟或者几分钟之前”。如果你再把“XX分钟之前”赋值给frame已经固定的timeView的话,那肯定就显示不正常啦。那怎么办呢???
第三 现在我们就要考虑,怎么让它显示正常呢,很简单,改变一下frame大小不就OK啦。我们把计算timeFrame的步骤放到YGOrginalView.m内的setUpFrame内即可,因为正好这个方法就刚刚在setUpData之前,我们更新了frame大小,就可以正常显示内容了。代码如下:
[code]// 时间 每次有新的时间都需要计算时间frame YGStatus *status = _statusFrame.status; CGFloat timeX = _nameView.frame.origin.x; CGFloat timeY = CGRectGetMaxY( _nameView.frame) + YGStatusCellMargin * 0.5; CGSize timeSize = [status.created_at sizeWithFont:YGTimeFont]; _timeView.frame = (CGRect){{timeX,timeY},timeSize}; // 来源 CGFloat sourceX = CGRectGetMaxX(_timeView.frame) + YGStatusCellMargin; CGFloat sourceY = timeY; CGSize sourceSize = [status.source sizeWithFont:YGSourceFont]; _sourceView.frame = (CGRect){{sourceX,sourceY},sourceSize};
因为来源的frame是依赖于时间的frame的,所以这里一并把来源的frame也给重新计算了。
13.2 微博来源处理
微博来源处理就比较简单了,因为来源不会跟随时间变化,我们只需要重写其set方法就可以了,代码如下:[code]- (void)setSource:(NSString *)source { // abc>微 3 1 // 微博 weibo.com</a> // <a href="http://weibo.com/" rel="nofollow">微博 weibo.com</a> // 微博 weibo.com NSRange range = [source rangeOfString:@">"]; source = [source substringFromIndex:range.location + range.length]; range = [source rangeOfString:@"<"]; source = [source substringToIndex:range.location]; source = [NSString stringWithFormat:@"来自%@",source]; _source = source; }
这里最主要的就是获取“>”和“<”的角标,通过角标来截取source内的字符串。
最后别忘了改变sourceView的文字颜色为浅灰色。
好啦,这节课就到这里吧,好好理解我们刚才是怎么处理时间显示问题的,会对你理解tableView的重用有很大帮助。
相关文章推荐
- 编写一个CocoaPods的spce文件
- Android开发笔记-下拉刷新上拉加载控件,对所有View通用!
- Android Support Library更新到v22.1之AppCompat新特性
- ios 取出subviews中指定subview
- android 常见分辨率(mdpi、hdpi 、xhdpi、xxhdpi )及屏幕适配注意事项
- Unity3D项目工程性能优化
- Android开发学习之路--Android Studio项目目录结构简介
- 安装Android adb驱动
- Android 中如何计算 App 的启动时间?
- Android开发学习之路--Android Studio项目目录结构简介
- openedx 安装 apparmor问题
- Android 混淆详解
- JFinal Model手动注册到TableMapping中的代码生成器
- android-IPC进程间通信
- android基础夯实2
- 陌陌凭什么排中国iOS收入榜社交第一?无需惊奇
- iOS去除icon图标特效,阴影,反光
- 【转】Objective-C消息机制的原理
- iOS 动态改变cell的高度
- iOS 编程中引用第三方的方类库的方法及常见问题