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

献给初学iOS的小盆友们——微博app项目开发之十三微博时间和来源处理

2016-01-28 13:27 399 查看
上节课我们基本把微博的主要数据都给展现出来了,数据也用视图模型给全部打通了。以后再遇到复杂的控件时候,先冷静分析,不要慌,然后划分界面结构,然后添加子控件,计算子控件的位置,如果控件内容由模型决定,就要想到使用MVVM概念,然后把模型转换为视图模型,最后给控件赋值模型视图。但是我们发现上节课的结果有两个地方特别让人不满意,一个是微博时间,一个是微博来源,这节课我们就主要解决这两个问题。

本节内容

微博时间处理

微博来源处理

本节资料

第十三节代码资料

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的重用有很大帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: