设备时间更改时执行功能

时间:2019-01-20 15:31:09

标签: ios swift time timer

我正在尝试在设备时钟更改时执行func。 该函数将返回学生的下一门课程,所有课程都位于一个数组中。

如果我理解正确,那么当设备时钟更改时,我们将无法执行func。 我读了一些人们说要使用60或其他时间计时器的主题,但是如果用户在08:05:07启动该应用程序,则该功能将在7秒钟后执行。 我以为可以使用do,但是我认为它将大量使用CPU,因此也会消耗电池。不?

有人有想法吗?

2 个答案:

答案 0 :(得分:0)

如果您只是想说要在某个特定的未来Date触发计时器,则应该只计算从现在到现在的时间(使用timeIntervalSince),然后使用那个。

例如,当前为“ 2019-01-20 17:11:59 +0000”,但是如果我希望它在17:15触发,您可以执行以下操作:

weak var timer: Timer?

func startTimer() {
    let futureDate = ISO8601DateFormatter().date(from: "2019-01-20T17:15:00Z")!
    let elapsed = futureDate.timeIntervalSince(Date())   // will be roughly 180.56 in this example at this moment of time

    timer?.invalidate() // invalidate prior timer, if any

    timer = Timer.scheduledTimer(withTimeInterval: elapsed, repeats: false) { [weak self] _ in
        // whatever you want to do at 17:15
    }
}

很显然,但是您提出的futureDate在您的情况下会有所不同,但这说明了这一想法。只需计算未来目标日期和现在之间的经过时间,并将其用于计时器即可。

现在,如果您真的担心时钟的更改,那么在iOS中,您可能会看到significantTimeChangeNotification,例如

NotificationCenter.default.addObserver(forName: UIApplication.significantTimeChangeNotification, object: nil, queue: .main) { [weak self] _ in
    // do something, maybe `invalidate` existing timer and create new one
    self?.startTimer()       
}

  

我原以为会用一段时间,但我认为它将大量使用CPU,因此也会消耗电池。不?

是的,循环旋转,等待一段时间会一直是一个坏主意。通常,您只需要设置一个计时器即可。

  

此函数将返回学生的下一门课程,所有课程都位于一个数组中。

这引起了一个问题,即该应用程序是否将在前台运行。如果您想在以后的某个时间通知用户,无论他们是否正在运行该应用,请考虑“ user notifications”。例如,请求通知权限:

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
    if !granted {
        // warn the user that they won't be notified after the user leaves the app unless they grant permission for notifications
        DispatchQueue.main.async {
            let alert = UIAlertController(title: nil, message: "We need permission to notify you of your class", preferredStyle: .alert)
            if let url = URL(string: UIApplication.openSettingsURLString) {
                alert.addAction(UIAlertAction(title: "Settings", style: .default) { _ in
                    UIApplication.shared.open(url)
                })
            }
            alert.addAction(UIAlertAction(title: "Cancel", style: .default))
            self.present(alert, animated: true)
        }
    }
}

然后,假设已授予权限,则安排一个通知:

let content = UNMutableNotificationContent()
content.title = "ClassTime"
content.body = "Time to go to math class"

let components = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: futureDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
let request = UNNotificationRequest(identifier: "Math 101", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)

答案 1 :(得分:0)

我做到了

    private var secondesActuelles : Int = 0
    private var timer = Timer()

    private func récuperLesSecondes(date : Date) -> Int {
        let date = date
        let calendar = Calendar.current
        let second = calendar.component(.second, from: date)
        return second
    }


    override func viewDidLoad() {
        super.viewDidLoad()

        secondesActuelles = récuperLesSecondes(date: Date())

        timer = Timer.scheduledTimer(withTimeInterval: TimeInterval(60 - secondesActuelles), repeats: false, block: { (timer) in
            print("l'heure a changé")
            self.secondesActuelles = self.récuperLesSecondes(date: Date())
            print("secondesActuelles : \(self.secondesActuelles)")

        })
}

它只能工作一次。但是在timeInterval之后就不会改变。