iOS|iOS 倒计时,date 一些坑
这几天做的东西涉及到日历类和时间类,各种操作。代码撸的要死。
这边注意下,在代码中撸的时间,系统默认都是格林时间 为基准的1获取当前时区时间 1.1获取当前时间类型为NSDate类型的 【iOS|iOS 倒计时,date 一些坑】获取当前时区
判断当前时区与格林时区的时间差
获取当前时间加上时间差
//获取当前时区时间
+(NSDate *)getCurrentLocaleDate:(NSDate *)ADate {NSTimeZone *timeZone = [NSTimeZone systemTimeZone];
NSTimeInterval interval = [timeZone secondsFromGMTForDate:ADate];
NSDate *nowDate = [ADate dateByAddingTimeInterval:interval];
return nowDate;
}
1.1获取当前时间类型为NSString类型的 系统提供了了一个NSDateFormatter 类
这个format的格式是
这个太TM重要了,我以前以为
大小写不区分的。蠢得要死,改了好长时间的BUG
大家一定要记住,不能乱写啊。乱写的话,转换就会出现问题。
G: 公元时代,例如AD公元
yy: 年的后2位
yyyy: 完整年
MM: 月,显示为1-12
MMM: 月,显示为英文月份简写,如 Jan
MMMM: 月,显示为英文月份全称,如 Janualy
dd: 日,2位数表示,如02
d: 日,1-2位显示,如 2
EEE: 简写星期几,如Sun
EEEE: 全写星期几,如Sunday
aa: 上下午,AM/PM
H: 时,24小时制,0-23
K:时,12小时制,0-11
m: 分,1-2位
mm: 分,2位
s: 秒,1-2位
ss: 秒,2位
S: 毫秒
//获取当前是时间 string
+(NSString *) getCurrentLocaleString:(NSDate *) Adate {
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
outputFormatter.locale = [NSLocale currentLocale];
[outputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
return [outputFormatter stringFromDate:Adate];
}
2.从服务器获取的时间 转换 我当时在从服务器获取时间之后,就用NSDateFormatter 格式化直接用了,结果感觉蹦蹦哒0.0
我们从服务器获取的时间都是我们当前时区的时间,可因为获取的类型不通,我们需要转换成不同的类型供我们使用, 上面的代码 思路都是
格式时间+时间差
因为系统是按照格林时间为基准的,你从服务器获取的时间 系统会认为是格林时间。 这时候你转换的时候,就要告诉系统,这是正确的时间 和格林时间差为0。
+(NSString *) stringFormDate:(NSDate *) Adate{
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[outputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
return [outputFormatter stringFromDate:Adate];
}
3 Date 的某一个元素 进行调整 项目中一开始有个需求就是对对明天后天 的这个时候做一些事情,我一开始想到就是就是加上时间差。最后感觉好蠢的感觉。查了一些资料,知道系统的提供的日历类,可以实现这些操作。
正书就是+ 负数就是?
+(NSDate *)addYear:(NSInteger)year Month:(NSInteger)month Day:(NSInteger)day date:(NSDate *)date{
//这个是日历类
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
//date元素类,可以对date的元素操作。
NSDateComponents *adcomps = [[NSDateComponents alloc] init];
[adcomps setYear:year];
[adcomps setMonth:month];
[adcomps setDay:day];
NSDate *date1 = [calendar dateByAddingComponents:adcomps toDate:date options:0];
return date1;
}
我这边只写了年月日 不过NSDateCompoents 提供了这么多属性。想怎么玩就怎么玩。
@property NSInteger era;
@property NSInteger year;
@property NSInteger month;
@property NSInteger day;
@property NSInteger hour;
@property NSInteger minute;
@property NSInteger second;
@property NSInteger nanosecond NS_AVAILABLE(10_7, 5_0);
@property NSInteger weekday;
@property NSInteger weekdayOrdinal;
@property NSInteger quarter NS_AVAILABLE(10_6, 4_0);
@property NSInteger weekOfMonth NS_AVAILABLE(10_7, 5_0);
@property NSInteger weekOfYear NS_AVAILABLE(10_7, 5_0);
@property NSInteger yearForWeekOfYear NS_AVAILABLE(10_7, 5_0);
4 Date 倒计时功能 项目中还需要实现倒计时功能,我第一个想到的就是全部换成 秒 进行运算(感觉自己蠢得要死)。
其实 实现倒计时功能挺简单的,但其中还挺多坑的。
我简单提一下,要实现倒计时2种方法。
一个用NSTimer(这个要涉及到NSRunLoop )
一个用GCD(这个写起来烦的要死,不过性能据说是杠杠的)
我代码都贴出来一下吧
4.1 NSTimer
//设置一个未来的时间 计算时间差
- (void)resetTimerWithDate:(NSDate *)futureDate{NSTimeInterval futureTimeInterval = [futureDate timeIntervalSinceDate:[[NSDate date] dateByAddingTimeInterval:3600*8]];
self.interval = futureTimeInterval;
if (self.timer == nil) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeDecrease:) userInfo:nil repeats:YES];
//因为我timer 是放在UI线程的 要指定NSRunloop的模式为NSRunLoopCommonModes
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
}- (void)timeDecrease:(NSTimer *)timer{
self.interval --;
if (self.interval <= 0) {
//如果计数器 = 0 或者 自己已经不在屏幕上了
[timer invalidate];
timer = nil;
return;
}
int day = self.interval/(3600*24);
int hour = (self.interval - day*(3600*24))/3600.0;
int min = (self.interval - day*(3600*24) - hour*3600)/60;
int sec = (self.interval - day*(3600*24) - hour*3600 - min*60);
NSArray *arr = @[@(day),@(hour),@(min),@(sec)];
//到这里已经可以获取到具体的时差 这边可以显示在你}
如果timer放在子线程里面, 可以不用设置Runloop的模式,但有一个要注意要手动启动runloop4.2GCD
//这个_timer 设置成成员变量
{
dispatch_source_t _timer;
}
//借用上面的计算时间间隔的方法 计算出时间间隔
__block int timeout = timeInterval;
//倒计时时间
//创建一个专门执行timer回调的GCD队列
dispatch_queue_t queue = dispatch_queue_create("my queue", 0);
//创建Timer
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//使用dispatch_source_set_timer函数设置timer参数
dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), interval, 0);
//设置回调
dispatch_source_set_event_handler(_timer, ^(){
if(timeout<=0)
{ //倒计时结束,关闭
dispatch_source_cancel(_timer);
_timer = nil;
dispatch_async(dispatch_get_main_queue(), ^{
//主线程显示
});
timeout--;
});
//dispatch_source默认是Suspended状态,通过dispatch_resume函数开始它
dispatch_resume(_timer);
关于rounloop和timer 可以看这边https://www.mgenware.com/blog/?p=459
推荐阅读
- 2020-04-07vue中Axios的封装和API接口的管理
- iOS中的Block
- 记录iOS生成分享图片的一些问题,根据UIView生成固定尺寸的分享图片
- 2019-08-29|2019-08-29 iOS13适配那点事
- Hacking|Hacking with iOS: SwiftUI Edition - SnowSeeker 项目(一)
- iOS面试题--基础
- 164《中考倒计时28~一模成绩出来了》
- 接口|axios接口报错-参数类型错误解决
- iOS|iOS 笔记之_时间戳 + DES 加密
- iOS,打Framework静态库