我有以下(terible)方法不断检查当前时间,并且当达到特定时间(在这种情况下是午夜)时,NSLog语句运行一次以表示正在执行的某些操作:
- (void) checkTime {
while (true){
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
NSDate *now = [[NSDate alloc] init];
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:@"HH:mm"];
NSString *nowDateString = [outputFormatter stringFromDate:now];
if([nowDateString isEqualToString:@"00:00"]){
NSLog(@"Store previous days data..");
BOOL stillMidnight = YES;
while(stillMidnight == YES){
NSDate *latestNow = [[NSDate alloc] init];
NSDateFormatter *latestOutputFormatter = [[NSDateFormatter alloc] init];
[latestOutputFormatter setDateFormat:@"HH:mm"];
NSString *latestString = [latestOutputFormatter stringFromDate:latestNow];
//Check if it is still midnight
if([latestString isEqualToString:@"00:01"]){
//leave while
stillMidnight = NO;
}
}
NSLog(@"No longer midnight");
}
[loopPool drain];
}
}
上面的方法从applicationDidFinishLaunchingWithOption方法调用如下:
[self performSelectorInBackground:@selector(checkTime) withObject:nil];
此代码在午夜运行NSLog(@"存储前几天的数据......"),这是我需要的,但这个问题有更优雅的解决方案吗?
谢谢,
杰克
答案 0 :(得分:5)
你会好起来的:
很容易安排一个重复计时器,该计时器首先使用(3)计算的日期和每24小时计算一次,但这将无法实现夏令时。所以,例如(直接在这里编码,未经测试)
- (void)scheduleNextTimedAction
{
// get the date now and the calendar the user is using
// (which will include their time zone, helpfully)
NSDate *dateNow = [NSDate date];
NSCalendar *relevantCalendar = [NSCalendar currentCalendar];
// decompose the current date to components; we'll
// just ask for month, day and year here for brevity;
// check out the other calendar units to decide whether
// that's something you consider acceptable
NSDateComponents *componentsForNow =
[relevantCalendar components:
NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:dateNow];
// we could explicitly set the time to midnight now,
// but since that's 00:00 it'll already be the value
// in the date components per the standard Cocoa object
// creation components, so...
// get the midnight that last occurred
NSDate *lastMidnight = [relevantCalendar dateFromComponents:componentsForNow];
// can we just add 24 hours to that? No, because of DST. So...
// create components that specify '1 day', however long that may be
NSDateComponents *oneDay = [[NSDateComponents alloc] init];
oneDay.day = 1;
// hence ask the calendar what the next midnight will be
NSDate *nextMidnight = [relevantCalendar
dateByAddingComponents:oneDay
toDate:lastMidnight
options:0];
[oneDay release];
// now create a timer to fire at the next midnight, to call
// our periodic function. NB: there's no convenience factory
// method that takes an NSDate, so we'll have to alloc/init
NSTimer *timer = [[NSTimer alloc]
initWithFireDate:nextMidnight
interval:0.0 // we're not going to repeat, so...
target:self
selector:@selector(doTimedAction:)
userInfo:nil
repeats:NO];
// schedule the timer on the current run loop
[[NSRunLoop currentRunLoop]
addTimer:timer
forMode: NSDefaultRunLoopMode];
// timer is retained by the run loop, so we can forget about it
[timer release];
}
- (void)doTimedAction:(NSTimer *)timer
{
NSLog(@"do action");
[self scheduleNextTimedAction];
}
答案 1 :(得分:3)
如果您想在任意时间点执行代码,最好设置本地通知。
答案 2 :(得分:0)
如果计时器还应在您的应用未运行Push notification guide或NSTimer时提醒用户,则可以使用UILocalNotification
,也可以使用触发日期或间隔进行初始化作为要调用的选择器。请注意,如果您的应用在后台,NSTimer
将无法触发,但在这种情况下,相反会在您的应用再次激活时触发。