一 日期处理
判断时间是不是今年
方法1:手机当前时间nowYear和selfYear比较
- (BOOL)isThisYear { NSCalendar *calendar = [NSCalendar currentCalendar]; // 获得年 NSInteger nowYear = [calendar component:NSCalendarUnitYear fromDate:[NSDate date]]; NSInteger selfYear = [calendar component:NSCalendarUnitYear fromDate:self]; return nowYear == selfYear; }
方法2:时间转字符串,比较字符串
- (BOOL)isThisYear
{
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy";
NSString *nowYear = [fmt stringFromDate:[NSDate date]];
NSString *selfYear = [fmt stringFromDate:self];
return [nowYear isEqualToString:selfYear];
}
判断是否为今天
方法1:年月日是否都一样
- (BOOL)isToday { NSCalendar *calendar = [NSCalendar currentCalendar]; NSDate *now = [NSDate date]; return [calendar component:NSCalendarUnitYear fromDate:now] == [calendar component:NSCalendarUnitYear fromDate:self] && [calendar component:NSCalendarUnitMonth fromDate:now] == [calendar component:NSCalendarUnitMonth fromDate:self] && [calendar component:NSCalendarUnitDay fromDate:now] == [calendar component:NSCalendarUnitDay fromDate:self]; }
方法2
- (BOOL)isToday { NSCalendar *calendar = [NSCalendar currentCalendar]; NSCalendarUnit unit = NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear; NSDateComponents *nowCmps = [calendar components:unit fromDate:[NSDate date]]; NSDateComponents *selfCmps = [calendar components:unit fromDate:self]; return nowCmps.year == selfCmps.year && nowCmps.month == selfCmps.month && nowCmps.day == selfCmps.day; }
方法3
- (BOOL)isToday { NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; fmt.dateFormat = @"yyyy-MM-dd"; NSString *nowString = [fmt stringFromDate:[NSDate date]]; NSString *selfString = [fmt stringFromDate:self]; return [nowString isEqualToString:selfString]; }
- 是否为昨天,不能直接用天数相减,需要增加判断
- (BOOL)isYesterday
{
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd";
// 获得只有年月日的时间
NSString *nowString = [fmt stringFromDate:[NSDate date]];
NSDate *nowDate = [fmt dateFromString:nowString];
NSString *selfString = [fmt stringFromDate:self];
NSDate *selfDate = [fmt dateFromString:selfString];
// 比较
NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit unit = NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear;
NSDateComponents *cmps = [calendar components:unit fromDate:selfDate toDate:nowDate options:0];
return cmps.year == 0
&& cmps.month == 0
&& cmps.day == 1;
}
同理,用(return cmps.year == 0
&& cmps.month == 0
&& cmps.day == -1)可以判断是否为明天
时间逻辑运算
今年时间显示格式
- 今天
1> 时间差距 < 1分钟,显示为“刚刚”;
2> 1分钟 =< 时间差距 <= 59分钟,显示为“xx分钟前”;
3> 时间差距 >= 1小时,显示为“xx小时前”; - 昨天
1> 昨天时间格式显示为“18:06:56”; - 其它
1> 时间格式显示为“08-07 18:06:56”;
- 今天
非今年时间显示格式
- 统一显示为“2014-08-07 18:06:56”;
- (NSString *)created_at
{
// 日期格式化类
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
// NSString -> NSDate
NSDate *createdAtDate = [fmt dateFromString:_created_at];
// 比较【发帖时间】和【手机当前时间】的差值
NSDateComponents *cmps = [createdAtDate intervalToNow];
if (createdAtDate.isThisYear) {
if (createdAtDate.isToday) { // 今天
if (cmps.hour >= 1) { // 时间差距 >= 1小时
return [NSString stringWithFormat:@"%zd小时前", cmps.hour];
} else if (cmps.minute >= 1) { // 1分钟 =< 时间差距 <= 59分钟
return [NSString stringWithFormat:@"%zd分钟前", cmps.minute];
} else {
return @"刚刚";
}
} else if (createdAtDate.isYesterday) { // 昨天
fmt.dateFormat = @"昨天 HH:mm:ss";
return [fmt stringFromDate:createdAtDate];
} else { // 今年的其他时间
fmt.dateFormat = @"MM-dd HH:mm:ss";
return [fmt stringFromDate:createdAtDate];
}
} else { // 非今年
return _created_at;
}
}
二 计算cell高度
Xib起名字注意:控制器加载Xib优先会加载没有..Controller的Xib,如果没有再加在..Controller的Xib
- 加载和xib类名一样的文件
+ (instancetype)viewFromXib
{
return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject];
}
- xib建一个懒加载,cell的set方法频繁调用,会加载很多xib
- (XMGTopicPictureView *)pictureView
{
if (!_pictureView) {
XMGTopicPictureView *pictureView = [XMGTopicPictureView viewFromXib];
[self.contentView addSubview:pictureView];
_pictureView = pictureView;
}
return _pictureView;
}
- 代码计算cell高度
- 标签高度+文字的高度+图片高度(判断)+底部工具条高度
#pragma mark - 代理方法
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// cell的高度
CGFloat cellHeight = XMGTopicTextY;
// 计算文字的高度
XMGTopic *topic = self.topics[indexPath.row];
CGFloat textW = XMGScreenW - 2 * XMGCommonMargin;
CGFloat textH = [topic.text sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize:CGSizeMake(textW, MAXFLOAT)].height;
cellHeight += textH + XMGCommonMargin;
// 中间内容的高度
if (topic.type != XMGTopicTypeWord) {
CGFloat contentW = textW;
// 图片的高度 * 内容的宽度 / 图片的宽度
CGFloat contentH = topic.height * contentW / topic.width;
cellHeight += contentH + XMGCommonMargin;
}
// 工具条的高度
cellHeight += XMGTopicToolbarH + XMGCommonMargin;
return cellHeight;
}
- 文字高度计算另一种写法
CGFloat textH = [topic.text boundingRectWithSize:CGSizeMake(textW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]} context:nil].size.height;
计算cell高度,拖拽时候重复调用,浪费性能,抽取代码放到模型里
重写方法,增加if (_cellHeight == 0) 判断,cell高度只计算一次;
- 计算图片的frame
- 图片尺寸拿到,用layoutsubviews布局
- (void)layoutSubviews
{
[super layoutSubviews];
self.pictureView.frame = topic.contentFrame;
}
- 会报错约束冲突
- 本来设置frame与最终显示效果不一样,注意下面属性:
// 清空自动伸缩属性
self.autoresizingMask = UIViewAutoresizingNone;
把cell的高度(cellHeight)和中间内容的frame(contentFrame)写到模型里面?
1. 模型是用来放数据的
2. 一个模型对应一个cellHeight和contentFrame
- 判断要不要添加gif标识
self.gifView.hidden = !topic.is_gif;
- 查看大图按钮是否隐藏
self.seeBigPictureButton.hidden = !topic.isBigPicture;
if (topic.isBigPicture) {
// 图片拉伸不带Scale就不会拉伸
self.imageView.contentMode = UIViewContentModeTop;
self.imageView.clipsToBounds = YES;
} else {
self.imageView.contentMode = UIViewContentModeScaleToFill; // 拉伸到填充整个iamgeview
self.imageView.clipsToBounds = NO;
}
- 如何判断图片是否gif图
- 判断路径最后格式名
NSString *ext = topic.image1.pathExtension.lowercaseString; // 转换为小写gif
self.gifView.hidden = ![ext isEqualToString:@"gif"];
取出文件第一个字节,可判断文件属于什么格式,前提要先下载完文件数据
三 下载进度条
- 设置展位图片的内容模式(View→Mode)
- Aspect Fit:伸缩到高度/宽度一致为止
- Aspect Fill:按宽高比伸缩到填充整个imageView,能看到整个图片为止
- 下载图片
// 进度条
@property (weak, nonatomic) IBOutlet DALabeledCircularProgressView *progressView;
[self.imageView sd_setImageWithURL:[NSURL URLWithString:topic.image1] placeholderImage:nil options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
// 每下载一点图片数据,就会调用一次这个block
weakSelf.progressView.hidden = NO;
weakSelf.progressView.roundedCorners = 5;
weakSelf.progressView.progress = 1.0 * receivedSize / expectedSize;
weakSelf.progressView.progressLabel.text = [NSString stringWithFormat:@"%.0f%%", weakSelf.progressView.progress * 100];
weakSelf.progressView.progressLabel.textColor = [UIColor whiteColor];
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
// 当图片下载完毕后,就会调用这个block
weakSelf.progressView.hidden = YES;
}];
- 设置进度条圆角和颜色只需要调用一次
- (void)awakeFromNib
{
// 清空自动伸缩属性
self.autoresizingMask = UIViewAutoresizingNone;
self.progressView.roundedCorners = 5;
self.progressView.progressLabel.textColor = [UIColor whiteColor];
self.imageView.userInteractionEnabled = YES; // 可以点击
[self.imageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageClick)]];
}
- 弹出大图片
- (void)imageClick
{
if (self.imageView.image == nil) return;
XMGSeeBigPictureViewController *seeBig = [[XMGSeeBigPictureViewController alloc] init];
seeBig.topic = self.topic;
[self.window.rootViewController presentViewController:seeBig animated:YES completion:nil];
}
四 保存大图片
- 查看大图控制器
- 图片尺寸超过屏幕高度,设置图片x和y为(0,0)
- 如果没有超过屏幕高度,居中显示
- (void)viewDidLoad {
[super viewDidLoad];
// 滚动控件
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = [UIScreen mainScreen].bounds;
scrollView.backgroundColor = [UIColor blackColor];
scrollView.delegate = self;
[self.view insertSubview:scrollView atIndex:0]; // 在数组最前面,保证所有控件放在前面
// 图片
UIImageView *imageView = [[UIImageView alloc] init];
[imageView sd_setImageWithURL:[NSURL URLWithString:self.topic.image1]];
[scrollView addSubview:imageView];
self.imageView = imageView;
// 图片的尺寸
imageView.x = 0;
imageView.width = XMGScreenW;
imageView.height = self.topic.height * imageView.width / self.topic.width;
if (imageView.height > XMGScreenH) { // 图片过长
imageView.y = 0;
scrollView.contentSize = CGSizeMake(0, imageView.height);
} else { // 图片居中显示
imageView.centerY = XMGScreenH * 0.5;
}
// 伸缩
CGFloat maxScale = self.topic.height / imageView.height;
if (maxScale > 1.0) {
scrollView.maximumZoomScale = maxScale;
}
}
- 图片实现伸缩
- 遵循UIscrollview代理
#pragma mark - <UIScrollViewDelegate>
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
五 相册图片
- 通过拍照获得一张图片
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:nil];
- 从相册中挑选一张图片
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentViewController:picker animated:YES completion:nil];
自定义照相机 : AVCaptureSession
- 遍历相册文件夹
ALAssetsLibrary *Library = [ALAssetsLibrary alloc] init;
// 遍历所有文件夹,一个ALAssetsGroup对象就代表一个文件夹
[Library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
// 遍历文件夹内的所有多媒体文件(图片、视频),一个ALAsset对象代表一张图片
[group enumerateAssetsUsingBlock^(ALAsset *result, NSUInteger index, BOOL *stop) {
XMGLog;
}];
} failureBlock:nil];
- 文件夹名字
- (NSString *)groupName
{
// 先从沙盒中取得名字
NSString *groupName = [[NSUserDefaults standardUserDefaults] stringForKey:XMGGroupNameKey];
if (groupName == nil) { // 沙盒中没有存储任何文件夹的名字
groupName = XMGDefaultGroupName;
// 存储名字到沙盒中
[[NSUserDefaults standardUserDefaults] setObject:groupName forKey:XMGGroupNameKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
return groupName;
}
- 添加一张图片到某个文件夹中
- (void)addImageToGroup:(ALAssetsGroup *)group
{
__weak ALAssetsLibrary *weakLibrary = self.library;
// 需要保存的图片
CGImageRef image = self.imageView.image.CGImage;
// 添加图片到【相机胶卷】
[weakLibrary writeImageToSavedPhotosAlbum:image metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) {
[weakLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {
// 添加一张图片到自定义的文件夹中
[group addAsset:asset];
[SVProgressHUD showSuccessWithStatus:@"保存成功!"];
} failureBlock:nil];
}];
}
- 保存图片
- (IBAction)save
{
// 获得文件夹的名字
__block NSString *groupName = [self groupName];
// self的弱引用
XMGWeakSelf;
// 图片库
__weak ALAssetsLibrary *weakLibrary = self.library;
// 创建文件夹
[weakLibrary addAssetsGroupAlbumWithName:groupName resultBlock:^(ALAssetsGroup *group) {
if (group) { // 新创建的文件夹
// 添加图片到文件夹中
[weakSelf addImageToGroup:group];
} else { // 文件夹已经存在
[weakLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
if ([name isEqualToString:groupName]) { // 是自己创建的文件夹
// 添加图片到文件夹中
[weakSelf addImageToGroup:group];
*stop = YES; // 停止遍历
} else if ([name isEqualToString:@"Camera Roll"]) {
// 文件夹被用户强制删除了
groupName = [groupName stringByAppendingString:@" "];
// 存储新的名字
[[NSUserDefaults standardUserDefaults] setObject:groupName forKey:XMGGroupNameKey];
[[NSUserDefaults standardUserDefaults] synchronize];
// 创建新的文件夹
[weakLibrary addAssetsGroupAlbumWithName:groupName resultBlock:^(ALAssetsGroup *group) {
// 添加图片到文件夹中
[weakSelf addImageToGroup:group];
} failureBlock:nil];
}
} failureBlock:nil];
}
} failureBlock:nil];
}