2014-12-01 68 views
1

我有经验,每分钟运行一次,像的NSTimer每分钟运行,但与的NSTimer第一第二

NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: Selector("everyMinute"), userInfo: nil, repeats: true) 

是否有可能使用的NSTimer,其他一些类,或其他一些控制,运行一些方法每分钟但在分钟的第一秒?

我有一些想法如何实现它在我自己,但我第一次检查是这个已经存在?

+0

你需要每分钟的第一秒,而不是仅仅一分钟一次有什么特别的原因吗?只是问,因为你正在运行的当前设备上的时间不太可能是完全正确的。 – Fogmeister 2014-12-01 15:59:11

+0

我认为问题是,反正是有,我们可以在正是我们所需要基于设备的时间的时间保证的东西执行。也想亲自了解这一点。 – Unheilig 2014-12-01 16:00:54

+0

@Fogmeister我想更新自定义标签的分钟数,但希望在+ 2秒内正确。但不想每秒都打电话给NSTimer。我知道这是疯狂的:-) – WebOrCode 2014-12-01 16:07:40

回答

7

一种方式将是使用NSCalendar找出当前下一分钟,并安排定时器从该开始,在runLoop

let date = NSDate() 
let calendar = NSCalendar.currentCalendar() 
let components = calendar.components(NSCalendarUnit.CalendarUnitEra|NSCalendarUnit.CalendarUnitYear|NSCalendarUnit.CalendarUnitMonth|NSCalendarUnit.CalendarUnitDay|NSCalendarUnit.CalendarUnitHour|NSCalendarUnit.CalendarUnitMinute, fromDate: date) 
components.minute += 1 
components.second = 1 
let nextMinuteDate = calendar.dateFromComponents(components) 
let timer = NSTimer(fireDate: nextMinuteDate!, interval: 60, target: self, selector: Selector("everyMinute"), userInfo: nil, repeats: true) 
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode) 
+0

我喜欢你的方法,我有同样的想法,但我的代码最终会变得更加复杂。 – WebOrCode 2014-12-01 16:34:23

+1

我猜你也可以设置'components.second = 0',我不认为你真的需要它是第一第二 – 2014-12-01 16:43:35

+1

非常不错的方式!是的components.second = 0更好。 – LastMove 2014-12-01 16:54:19

1

的的NSDate方法,因为一月timeIntervalSinceReferenceDate返回的秒数手动调度1,2001,格林威治标准时间上午12:00。它包括的第二

分数如果你调用,除以60,取最低值,然后乘以60,它应该给你目前的“圆分钟”的时间间隔。将60加到上面,你得到下一个“round minute”的时间间隔,给THAT加1,在下一个“round minute”之后你得到一秒的时间间隔

代码可能看起来像这样的:

NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; 
NSTimeInterval nextMinute = floor(now/60)*60 + 61 //time interval for next minute, plus 1 second 
NSTimeInterval delay = nextMinute - now; 
//Delay now contains the number of seconds until the next "round minute", plus 1 second. 

dispatch_after(
    dispatch_time(DISPATCH_TIME_NOW, 
    (int64_t)(delay * NSEC_PER_SEC)), 
    dispatch_get_main_queue(),^
    { 
    //Replace the code below with whatever target/userInfo you need. 
    [NSTimer scheduledTimerWithTimeInterval: 60 
     target: self 
     userInfo: nil; 
     repeats: YES]; 
    } 
); 

编辑:其实,一分钟的“第一第二”是第零秒,所以你应该改变+61在计算nextMinute为“+60”上面的代码,而不是“+61”

+0

你的逻辑和法比奥的答案一样,有一些区别吗? – WebOrCode 2014-12-01 19:20:24

+0

我的解决方案使用纯算术。法比奥需要使用NSCalendar和NSDateComponents。 – 2014-12-01 19:27:54

+0

let delay = 60 - NSDate.timeIntervalSinceReferenceDate()%60 – 2016-05-31 07:22:04

0

The accepted answer,updated for Swift 4:

let date = Date() 
let calendar = Calendar.current 
var components = calendar.dateComponents([.era, .year, .month, .day, .hour, .minute], from: date) 

guard let minute = components.minute else { return } 
components.second = 0 
components.minute = minute + 1 

guard let nextMinute = calendar.date(from: components) else { return } 

let timer = Timer(fire: nextMinute, interval: 60, repeats: true) { [weak self] timer in 
    self?.everyMinute() 
} 
RunLoop.main.add(timer, forMode: .defaultRunLoopMode)