我有一个复杂的问题需要描述,所以我会保存它并总结一下我想要做的事情.当状态栏上的时间发生变化时,我希望"得到通知",这样我就可以重新计算时间.我正在计算时间,直到很好,但是有一个1分钟的窗口,我的计算和时间戳不匹配...这一切都取决于他们何时打开应用程序,相比iPhone"秒"时钟的时间他们打开了它.
简而言之,我们可以检测状态栏上的分钟何时发生变化吗?如果是这样,怎么样?
谢谢!
mja*_*mja 10
甚至比Emilio的答案更简单 - 当您的视图加载时(或当您想要触发事件时)只检查当前日期的秒部分(例如,使用NSCalendar),安排一个将在60-currentSeconds中触发的计时器(将是下一分钟,零秒)最后,安排每60秒发射一次的新计时器.
根据@ mja的建议:
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSSecondCalendarUnit fromDate:[NSDate date]];
NSInteger currentSecond = [components second];
//+1 to ensure we fire right after the minute change
NSDate *fireDate = [[NSDate date] dateByAddingTimeInterval:60 - currentSecond + 1];
NSTimer *timer = [[NSTimer alloc] initWithFireDate:fireDate
interval:60
target:self
selector:@selector(YOURSELECTORHERE)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
Run Code Online (Sandbox Code Playgroud)
我正在使用它并且效果很好.如果您需要移除计时器,则必须更加小心.
小智 5
基于 @SG1 代码示例,但使用 Swift:
// Calculate fireDate on every minute's first second
let now: Date = Date()
let calendar: Calendar = Calendar.current
let currentSeconds: Int = calendar.component(.second, from: now)
// Init timer
self.timer = Timer(
fire: now.addingTimeInterval(Double(60 - currentSeconds + 1)),
interval: 60 /*seconds*/,
repeats: true,
block: { (t: Timer) in
self.sendNotification()
})
// Start timer
RunLoop.main.add(self.timer, forMode: RunLoopMode.defaultRunLoopMode)
private func sendNotification(){
...
}
Run Code Online (Sandbox Code Playgroud)
我深入研究并找到了该Calendar.nextDate(after:matching:matchingPolicy:repeatedTimePolicy:direction:)方法,根本不需要在应用程序代码中进行任何计算。
例子:
var zeroSeconds = DateComponents()
zeroSeconds.second = 0
guard let nextMinute = Calendar(identifier: .gregorian).nextDate(after: Date(), matching: zeroSeconds, matchingPolicy: .nextTime, direction: .forward) else {
// This should not happen since there should always be a next minute
return
}
let timer = Timer(fire: nextMinute.advanced(by: 0.1), interval: 60, repeats: true) { _ in
// This runs at every turn of a minute
}
RunLoop.main.add(timer, forMode: .default)
Run Code Online (Sandbox Code Playgroud)
正如其他答案所指出的,一些缓冲区似乎是必要的,以确保在分钟结束后触发它(例如,如果您每分钟显示一次时间,则至关重要),因此是 nextMinute.advanced(by: 0.1)(100毫秒)。我还没有找到任何关于具体时间的文档,但在我的简短测试中,100 毫秒似乎还可以。
这就是我要做的:
当应用程序启动时,我会启动一个计时器,每秒更新一次以检查时间何时变化。
当我第一次发现时间变化时,我会使该计时器无效并启动一个每分钟触发一次的计时器。
该分钟计时器将与状态栏上的时钟同步,延迟不超过一秒。
| 归档时间: |
|
| 查看次数: |
1618 次 |
| 最近记录: |