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

时间处理

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

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。

效果:

iOS 新浪微博-5.1 首页微博列表_时间/配图-LMLPHP

配图

第一步:通过查看新浪微博的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 首页微博列表_时间/配图-LMLPHP

04-20 22:34