在上一篇中,我们已经把首页微博显示出来了,但还有很多细节,需要我们去调整的。这一章中,我们将处理好时间,配图,工具框及转发微博等小细节的功能。

时间处理

第一步:定义一个时间的类别,用于判断是昨天、今天等。

NSDate+Time.h

#import <Foundation/Foundation.h>

@interface NSDate (Time)
/**
* 判断某个时间是否为今年
*/
- (BOOL)isThisYear;
/**
* 判断某个时间是否为昨天
*/
- (BOOL)isYesterday;
/**
* 判断某个时间是否为今天
*/
- (BOOL)isToday;
@end

NSDate+Time.m

//
// NSDate+Time.m
// Weibo
//
// Created by jiangys on 15/10/25.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import "NSDate+Time.h" @implementation NSDate (Time) /**
* 判断某个时间是否为今年
*/
- (BOOL)isThisYear
{
NSCalendar *calendar = [NSCalendar currentCalendar];
// 获得某个时间的年月日时分秒
NSDateComponents *dateCmps = [calendar components:NSCalendarUnitYear fromDate:self];
NSDateComponents *nowCmps = [calendar components:NSCalendarUnitYear fromDate:[NSDate date]];
return dateCmps.year == nowCmps.year;
} /**
* 判断某个时间是否为昨天
*/
- (BOOL)isYesterday
{
NSDate *now = [NSDate date]; // date == 2014-04-30 10:05:28 --> 2014-04-30 00:00:00
// now == 2014-05-01 09:22:10 --> 2014-05-01 00:00:00
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd"; // 2014-04-30
NSString *dateStr = [fmt stringFromDate:self];
// 2014-10-18
NSString *nowStr = [fmt stringFromDate:now]; // 2014-10-30 00:00:00
NSDate *date = [fmt dateFromString:dateStr];
// 2014-10-18 00:00:00
now = [fmt dateFromString:nowStr]; NSCalendar *calendar = [NSCalendar currentCalendar]; NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents *cmps = [calendar components:unit fromDate:date toDate:now options:]; return cmps.year == && cmps.month == && cmps.day == ;
} /**
* 判断某个时间是否为今天
*/
- (BOOL)isToday
{
NSDate *now = [NSDate date];
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd"; NSString *dateStr = [fmt stringFromDate:self];
NSString *nowStr = [fmt stringFromDate:now]; return [dateStr isEqualToString:nowStr];
} @end

第二步:在Status.m中重写时间的属性

/**
* 时间处理,重写 1.今年
1> 今天
* 1分内: 刚刚
* 1分~59分内:xx分钟前
* 大于60分钟:xx小时前 2> 昨天
* 昨天 xx:xx 3> 其他
* xx-xx xx:xx 2.非今年
1> xxxx-xx-xx xx:xx
*/
- (NSString *)created_at
{ NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
// 如果是真机调试,转换这种欧美时间,需要设置locale
fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; // 设置日期格式(声明字符串里面每个数字和单词的含义)
// E:星期几
// M:月份
// d:几号(这个月的第几天)
// H:24小时制的小时
// m:分钟
// s:秒
// y:年
fmt.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
// _created_at = @"Tue Sep 30 17:06:25 +0600 2014"; // 微博的创建日期
NSDate *createDate = [fmt dateFromString:_created_at];
// 当前时间
NSDate *now = [NSDate date]; // 日历对象(方便比较两个日期之间的差距)
NSCalendar *calendar = [NSCalendar currentCalendar];
// NSCalendarUnit枚举代表想获得哪些差值
NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
// 计算两个日期之间的差值
NSDateComponents *cmps = [calendar components:unit fromDate:createDate toDate:now options:]; if ([createDate isThisYear]) { // 今年
if ([createDate isYesterday]) { // 昨天
fmt.dateFormat = @"昨天 HH:mm";
return [fmt stringFromDate:createDate];
} else if ([createDate isToday]) { // 今天
if (cmps.hour >= ) {
return [NSString stringWithFormat:@"%d小时前", (int)cmps.hour];
} else if (cmps.minute >= ) {
return [NSString stringWithFormat:@"%d分钟前", (int)cmps.minute];
} else {
return @"刚刚";
}
} else { // 今年的其他日子
fmt.dateFormat = @"MM-dd HH:mm";
return [fmt stringFromDate:createDate];
}
} else { // 非今年
fmt.dateFormat = @"yyyy-MM-dd HH:mm";
return [fmt stringFromDate:createDate];
}
}

这样,就可以显示出来了,但会有问题,就是不断的下拉刷新时,本来显示“刚刚”字样的,刷新后,可能变为“1分钟前”。由于“刚刚”的字体size不变化,因而显示“1分钟前”会导致显示不全。改进方法

    /** 时间 */
// self.timeLabel.text = status.created_at;
// self.timeLabel.frame = statusFrame.timeLabelF; /** 来源 */
// self.sourceLabel.text = status.source;
// self.sourceLabel.frame = statusFrame.sourceLabelF; /** 时间 */
NSString *time = status.created_at;
CGFloat timeX = statusFrame.nameLabelF.origin.x;
CGFloat timeY = CGRectGetMaxY(statusFrame.nameLabelF) + StatusCellBorderW;
CGSize timeSize = [time sizeWithFont:StatusCellTimeFont];
self.timeLabel.frame = (CGRect){{timeX, timeY}, timeSize};
self.timeLabel.text = time; /** 来源 */
CGFloat sourceX = CGRectGetMaxX(self.timeLabel.frame) + StatusCellBorderW;
CGFloat sourceY = timeY;
CGSize sourceSize = [status.source sizeWithFont:StatusCellSourceFont];
self.sourceLabel.frame = (CGRect){{sourceX, sourceY}, sourceSize};
self.sourceLabel.text = status.source;

这样,每重新加载cell时,都重新计算一遍时间和来源的size。

效果:

配图

第一步:通过查看新浪微博的API,我们可以看到,返回的配图是一个集合。先定义好集合里的模型

Photo.h

#import <Foundation/Foundation.h>

@interface Photo : NSObject
/** 缩略图地址 */
@property (nonatomic, copy) NSString *thumbnail_pic;
@end

第二步:在Status模型了,添加配图的集合属性,并指定,里面的集合是由Photo这个模型来构成的。

Status.h

/** 微博配图地址。多图时返回多图链接。无配图返回“[]” */
@property (nonatomic, strong) NSArray *pic_urls;

Status.m ,需要引用 #import "MJExtension.h"

+ (NSDictionary *)objectClassInArray
{
return @{@"pic_urls" : [Photo class]};
}

第三步:拿到数据之后,接下来要做的事情

  1. 定义一个配图的View
  2. 定义一个装了该微博所有的配图View的容器
  3. 往容器里填充配图
  4. 计算这个容器的宽高

1.定义一个配图的View

StatusPhotoView.h

#import <UIKit/UIKit.h>
@class Photo; @interface StatusPhotoView : UIImageView /** 图片模型 */
@property (nonatomic, strong) Photo *photo; @end

StatusPhotoView.m

//
// StatusPhotoView.m
// Weibo
//
// Created by jiangys on 15/10/25.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import "StatusPhotoView.h"
#import "Photo.h"
#import "UIImageView+WebCache.h" @interface StatusPhotoView()
@property (nonatomic, weak) UIImageView *gifView;
@end @implementation StatusPhotoView - (UIImageView *)gifView
{
if (!_gifView) {
UIImage *image = [UIImage imageNamed:@"timeline_image_gif"];
UIImageView *gifView = [[UIImageView alloc] initWithImage:image];
[self addSubview:gifView];
self.gifView = gifView;
}
return _gifView;
} - (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 内容模式
self.contentMode = UIViewContentModeScaleAspectFill;
// 超出边框的内容都剪掉
self.clipsToBounds = YES;
}
return self;
} - (void)setPhoto:(Photo *)photo
{
_photo = photo; // 设置图片
[self sd_setImageWithURL:[NSURL URLWithString:photo.thumbnail_pic] placeholderImage:[UIImage imageNamed:@"timeline_image_placeholder"]]; // 显示\隐藏gif控件
// 判断是够以gif或者GIF结尾
self.gifView.hidden = ![photo.thumbnail_pic.lowercaseString hasSuffix:@"gif"];
} - (void)layoutSubviews
{
[super layoutSubviews]; self.gifView.x = self.width - self.gifView.width;
self.gifView.y = self.height - self.gifView.height;
}
@end

2.定义一个装了该微博所有的配图View的容器

StatusPhotosView.h

#import <UIKit/UIKit.h>

@interface StatusPhotosView : UIView

/** 图片模型 */
@property (nonatomic, strong) NSArray *photos; /**
* 根据图片个数计算相册的尺寸
*/
+ (CGSize)sizeWithCount:(NSUInteger)count;
@end

StatusPhotosView.m

//
// StatusPhotosView.m
// Weibo
//
// Created by jiangys on 15/10/25.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import "StatusPhotosView.h"
#import "StatusPhotoView.h"
#import "Photo.h" #define StatusPhotoWH 70
#define StatusPhotoMargin 10
#define StatusPhotoMaxCol(count) ((count==4)?2:3) @implementation StatusPhotosView - (void)setPhotos:(NSArray *)photos
{
_photos = photos; NSUInteger photosCount = photos.count; // 创建足够多的图片控制
while (self.subviews.count < photosCount) {
StatusPhotoView *photoView = [[StatusPhotoView alloc] init];
[self addSubview:photoView];
} // 遍历所有的图片控件,设置图片
for (int i = ; i < self.subviews.count; i++) {
StatusPhotoView *photoView = self.subviews[i]; if (i < photosCount) {
photoView.photo = photos[i];
photoView.hidden = NO;
} else{
photoView.hidden=YES;
}
} } - (void)layoutSubviews
{
[super layoutSubviews]; // 设置图片的尺寸和位置
NSUInteger photosCount = self.photos.count;
int maxCol = StatusPhotoMaxCol(photosCount);
for (int i = ; i<photosCount; i++) {
StatusPhotoView *photoView = self.subviews[i]; int col = i % maxCol;
photoView.x = col * (StatusPhotoWH + StatusPhotoMargin); int row = i / maxCol;
photoView.y = row * (StatusPhotoWH + StatusPhotoMargin);
photoView.width = StatusPhotoWH;
photoView.height = StatusPhotoWH;
}
} + (CGSize)sizeWithCount:(NSUInteger)count
{
// 最大列数(一行最多有多少列)
int maxCols = StatusPhotoMaxCol(count); NSUInteger cols = (count >= maxCols)? maxCols : count;
CGFloat photosW = cols * StatusPhotoWH + (cols - ) * StatusPhotoMargin; // 行数
NSUInteger rows = (count + maxCols - ) / maxCols;
CGFloat photosH = rows * StatusPhotoWH + (rows - ) * StatusPhotoMargin; return CGSizeMake(photosW, photosH);
}
@end

3.StatusFrame.m里计算配图的宽高

    /** 配图 */
CGFloat originalH = ;
if (status.pic_urls.count) { // 有配图
CGFloat photosX = contentX;
CGFloat photosY = CGRectGetMaxY(self.contentLabelF) + StatusCellBorderW;
CGSize photosSize = [StatusPhotosView sizeWithCount:status.pic_urls.count];
_photosViewF = (CGRect){{photosX, photosY}, photosSize}; originalH = CGRectGetMaxY(self.photosViewF) + StatusCellBorderW;
} else { // 没配图
originalH = CGRectGetMaxY(self.contentLabelF) + StatusCellBorderW;
}

4.在StatusCell.m里创建定义容器,初始化容器并赋值

/** 配图 */
@property (nonatomic, weak) StatusPhotosView *photosView;

初始化容器initWithStyle

        /** 配图 */
StatusPhotosView *photosView = [[StatusPhotosView alloc] init];
[originalView addSubview:photosView];
self.photosView = photosView;

赋值setStatusFrame

    /** 配图 */
if (status.pic_urls.count) {
self.photosView.frame = statusFrame.photosViewF;
self.photosView.photos = status.pic_urls;
self.photosView.hidden = NO;
} else {
self.photosView.hidden = YES;
}

效果如下图:

iOS 新浪微博-5.1 首页微博列表_时间/配图的更多相关文章

  1. iOS 新浪微博-5.2 首页微博列表_转发微博/工具栏

    继续于上一篇,还是做首页的功能,这一篇把剩下的首页继续完善. 看看上面的图片,分析: 1.转发微博里面的内容,和原创微博是一样的,由文字+配图组成.这应该放在一个UIView里处理. 2.工具栏也当成 ...

  2. iOS 新浪微博-5.3 首页微博列表_集成图片浏览器

    实际上,我们可以使用李明杰在教程里集成的MJPhotoBrowser,地址: http://code4app.com/ios/快速集成图片浏览器/525e06116803fa7b0a000001 使用 ...

  3. iOS 新浪微博-5.0 首页微博列表

    首页显示微博列表,是微博的核心部分,这一章节,我们主要是显示出微博的列表. 导入第三方类库 pod 'SDWebImage', '~> 3.7.3' pod 'MJRefresh', '~> ...

  4. IOS SWIFT UITableView 实现简单微博列表

    // // Weibo.swift // UITableViewCellExample // // Created by XUYAN on 15/8/15. // Copyright (c) 2015 ...

  5. Day8-微信小程序实战-交友小程序-首页用户列表渲染及多账号调试及其点赞功能的实现

    在这之前已经把编辑个人的所有信息的功能已经完成了 之后先对首页的列表搞动态的,之前都是写死的静态 1.之前都是把好友写死的,现在就在js里面定义一个数组,用循环来动态的绑定 在onReady中定义,取 ...

  6. 【Android 我的博客APP】1.抓取博客首页文章列表内容——网页数据抓取

    打算做个自己在博客园的博客APP,首先要能访问首页获取数据获取首页的文章列表,第一步抓取博客首页文章列表内容的功能已实现,在小米2S上的效果图如下: 思路是:通过编写的工具类访问网页,获取页面源代码, ...

  7. PHPCMS v9 实现首页,列表页,内容页调用点击量方法

    大家好,今天有点闲,看很多朋友经常问PHPCMS v9 首页,列表页,内容页调用点击怎么弄,打算抽时间把代码全部归纳出来,以便大家日后使用,如下: 1,首页调用点击量 {pc:content acti ...

  8. 织梦首页、列表页调用文章body内容的两种方法

    http://blog.csdn.net/langyu1021/article/details/52261411 关于首页.列表页调用文章body内容的两种方法,具体方法如下: 第一种方法: {ded ...

  9. iOS 新浪微博-1.1框架升级

    在iOS 新浪微博-1.0框架搭建 中,使用的是xcode5.1.1开发.现在把重整了一下框架 改为xcode7.0开发 使用cocoaPad管理第三方库 程序将托管到github上 在改为xcode ...

随机推荐

  1. Linux 创建文件系统及挂载文件系统流程详解(转)

    作者:北南南北 来自: LinuxSir.Org 摘要:本文对新增硬盘,切割硬盘,创建硬盘分区,为硬盘分区创建文件系统,以及加载文件系统的流程做总结性论述:主要是为初学者弄清楚这一操作过程:本文涉及f ...

  2. 解决ubuntu系统“XXX is not in the sudoers file”错误

    用adduser新建的用户,当时只输入了一个用户名,没做其它操作,这样就建立了一个normal用户.在执行sudo vim hadoop-env.sh时,报“*** is not in the sud ...

  3. python中的一个现象,db.commit和db.commit()

    假设有一个表,有自增字段,在开发环境中(sublime/Liclipse等)执行insert语句时,如果调用db.commit,那么数据库中不会有这条记录,但也不报错,再次插入成功时,自增自段加1. ...

  4. [No0000178]改善C#程序的建议1:非用ICloneable不可的理由

    好吧,我承认,这是一个反标题,实际的情况是:我找不到一个非用ICloneable不可的理由.事实上,接口ICloneable还会带来误解,因为它只有一个Clone方法. 我们都知道,对象的拷贝分为:浅 ...

  5. RabbitMQ 内存控制 硬盘控制

    RabbitMQ服务器在启动时以及abbitmqctl set_vm_memory_high_watermark fraction 执行时,会检查计算机的RAM总大小. 默认情况下下, 当 Rabbi ...

  6. #include<stdio.h> #include "stdio.h"

    https://baike.baidu.com/item/#include <stdio.h> #include <stdio.h> 编辑 #include<stdio. ...

  7. int 4 bytes

    http://waynewhitty.ie/blog-post.php?id=19 MySQL - INT(11) vs BIGINT(11) vs TINYINT(11) This seems to ...

  8. PHP之错误

    三.PHP配置之Error handling logging 1.error_reporting integer error_reporting = E_ALL 设置错误报告的级别.该参数可以是一个任 ...

  9. [daily][gnucash] 复式记账

    管理, 是成就人生的第一步. 管钱,是第一步中的第一小步. 选了又选,终于选了一个软件,gnucash, 但是, 他有点专业, 用之前需要搞懂一下会计概念. 即: 复式记账 gnucash手册的这一章 ...

  10. ps命令参数

    1.查看父进程ps -ef |grep <进程名>在显示的输出中,第三列就是该进程的父进程PID,然后可以再使用ps命令来查看父进程的名称ps -ef |grep <父进程PID&g ...