最近想整理下關(guān)于OC的工具類,常用到的也方便自己之后查閱,也可以給需要的朋友參考。
1、兩種倒計(jì)時(shí)
-
第一種:
GCD
__block NSInteger timeout = time;//可以假設(shè)time等于60秒
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒執(zhí)行
dispatch_source_set_event_handler(_timer, ^{
if(timeout<=0){ //倒計(jì)時(shí)結(jié)束,關(guān)閉
dispatch_source_cancel(_timer);
dispatch_async(dispatch_get_main_queue(), ^{
//主線程中處理UI
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
//主線程中處理UI
presellTimeLB.text = [self dateFormatDays_Hours_MinsWith:timeout];
});
timeout--;
}
});
dispatch_resume(_timer);
這里我假設(shè)我有一個(gè)名為presellTimeLB的Label,處理倒計(jì)時(shí)的方法dateFormatDays_Hours_MinsWith: (僅供參考)
- (NSString *)dateFormatDays_Hours_MinsWith:(NSInteger)time
{
NSInteger days = 0,hours = 0,minutes = 0,second = 0;
NSInteger daySeconds = 24*60*60;
//獲取天數(shù)
if (time >= daySeconds) {
days = time/daySeconds;
time = time%daySeconds;
}
//獲取小時(shí)數(shù)
if(time>=60*60){
hours = time/3600;
time = time%3600;
}
//獲取分鐘數(shù)
if (time>=60) {
minutes = time/60;
time = time%60;
}
//獲取秒數(shù)
second = time;
if (days>0) {
return [NSString stringWithFormat:@"%ld天%ld時(shí)%ld分",(long)days,(long)hours,(long)minutes];
}else{
return [NSString stringWithFormat:@"%ld時(shí)%ld分%ld秒",(long)hours,(long)minutes,(long)second];
}
}
-
第二種:
NSTimer
1)聲明
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerFireMethod:) userInfo:nil repeats:YES];
2)實(shí)現(xiàn)select方法
- (void)timerFireMethod:(NSTimer *)theTimer
{
timer = theTimer;
static NSInteger hhh;
if (timeStart) {
hhh = [self.leftTime integerValue];
timeStart = NO;
}
if (hhh <= 1) {
preSellView.hidden = YES;
//注①
[timer invalidate];
}else {
//注②
[[NSRunLoop currentRunLoop] addTimer:theTimer forMode:NSRunLoopCommonModes];
hhh--;
dispatch_async(dispatch_get_main_queue(), ^{
[presellTimeLB setText:[self dateFormatDays_Hours_MinsWith:hhh]];
});
}
}
注:
①NSTimer對(duì)象用完之后必須進(jìn)行invalidate,NSTimer才會(huì)消失。比如說(shuō)你還需要考慮到倒計(jì)時(shí)沒(méi)結(jié)束時(shí)退出當(dāng)前頁(yè)面時(shí)是不是也需要把當(dāng)前的NSTimer invalidate呢?
②這里為什么要用NSRunLoop寫這句代碼呢?如果沒(méi)有這句代碼,會(huì)發(fā)現(xiàn)在界面上滾動(dòng)一個(gè)scrollView,那么滾動(dòng)停止前,timer像是暫停了一樣,其實(shí)這是runloop的mode在作怪。
runloop可以理解為cocoa下的一種消息循環(huán)機(jī)制,用來(lái)處理各種消息事件,我們?cè)陂_發(fā)的時(shí)候并不需要手動(dòng)去創(chuàng)建一個(gè)runloop,因?yàn)榭蚣転槲覀儎?chuàng)建了一個(gè)默認(rèn)的runloop,通過(guò)[NSRunloop currentRunloop]我們可以得到一個(gè)當(dāng)前線程下面對(duì)應(yīng)的runloop對(duì)象,不過(guò)我們需要注意的是不同的runloop之間消息的通知方式。
在開啟一個(gè)NSTimer實(shí)質(zhì)上是在當(dāng)前的runloop中注冊(cè)了一個(gè)新的事件源,而當(dāng)scrollView滾動(dòng)的時(shí)候,當(dāng)前的MainRunLoop是處于UITrackingRunLoopMode的模式下,在這個(gè)模式下,是不會(huì)處理NSDefaultRunLoopMode的消息(因?yàn)镽unLoop Mode不一樣),要
要想在scrollView滾動(dòng)的同時(shí)也響應(yīng)其他runloop的消息,需要改變兩者之間的runloopMode.
[[NSRunLoop currentRunLoop] addTimer:theTimer forMode:NSRunLoopCommonModes];
-
NSTimer 的另一種寫法
- (void)timerFireMethod:(NSTimer *)theTimer
{
NSCalendar *cal = [NSCalendar currentCalendar];//定義一個(gè)NSCalendar對(duì)象
NSDateComponents *endTime = [[NSDateComponents alloc] init]; //初始化目標(biāo)時(shí)間...
NSDate *today = [NSDate date]; //得到當(dāng)前時(shí)間
NSDate *date = [NSDate dateWithTimeInterval:80 sinceDate:today];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *dateString = [dateFormatter stringFromDate:date];
static int year;
static int month;
static int day;
static int hour;
static int minute;
static int second;
if(timeStart) {//從NSDate中取出年月日,時(shí)分秒,但是只能取一次
year = [[dateString substringWithRange:NSMakeRange(0, 4)] intValue];
month = [[dateString substringWithRange:NSMakeRange(5, 2)] intValue];
day = [[dateString substringWithRange:NSMakeRange(8, 2)] intValue];
hour = [[dateString substringWithRange:NSMakeRange(11, 2)] intValue];
minute = [[dateString substringWithRange:NSMakeRange(14, 2)] intValue];
second = [[dateString substringWithRange:NSMakeRange(17, 2)] intValue];
timeStart= NO;
}
[endTime setYear:year];
[endTime setMonth:month];
[endTime setDay:day];
[endTime setHour:hour];
[endTime setMinute:minute];
[endTime setSecond:second];
NSDate *todate = [cal dateFromComponents:endTime]; //把目標(biāo)時(shí)間裝載入date
//用來(lái)得到具體的時(shí)差,是為了統(tǒng)一成北京時(shí)間
unsigned int unitFlags = NSYearCalendarUnit| NSMonthCalendarUnit| NSDayCalendarUnit| NSHourCalendarUnit| NSMinuteCalendarUnit| NSSecondCalendarUnit;
NSDateComponents *d = [cal components:unitFlags fromDate:today toDate:todate options:0];
NSString *h = [NSString stringWithFormat:@"%ld",(long)[d hour]];
NSString *fen = [NSString stringWithFormat:@"%ld", (long)[d minute]];
if([d minute] < 10) {
fen = [NSString stringWithFormat:@"%ld",[d minute]];
}
NSString *miao = [NSString stringWithFormat:@"%ld", (long)[d second]];
if([d second] < 10) {
miao = [NSString stringWithFormat:@"0%ld",(long)[d second]];
}
if([d second] >= 0) {
//計(jì)時(shí)尚未結(jié)束,do_something
dispatch_async(dispatch_get_main_queue(), ^{
[[NSRunLoop currentRunLoop] addTimer:theTimer forMode:NSRunLoopCommonModes];
[presellTimeLB setText:[NSString stringWithFormat:@"%ld時(shí)%ld分%ld秒",[h integerValue],[fen integerValue], [miao integerValue]]];
});
} else{
//倒計(jì)時(shí)結(jié)束,do something
[theTimer invalidate];
}
}
注:這里我們以80秒倒計(jì)時(shí)為例,還是假設(shè)我有一個(gè)BOOL類型的timeStart為了取一次原始時(shí)間,有名為presellTimeLB的Laber,nsrunloop改變mode的狀態(tài)照樣寫上。這里把時(shí)間處理和邏輯判斷寫在了一起。