【问题标题】:Best way to fire a function when current time reaches a specific time当前时间达到特定时间时触发功能的最佳方式
【发布时间】:2024-01-13 18:43:01
【问题描述】:

嘿,我想在设备时钟到达下午 6 点时将应用程序的模式从白天更改为夜间,并在时钟到达上午 6 点时再次更改。现在我每秒都在使用 Timer 来检查时间并触发我的功能。但我觉得这不是最好的方法。

【问题讨论】:

    标签: timer swift4.1


    【解决方案1】:

    您好,是的,您的方法不是最好的方法,因为这会消耗用户设备的电池寿命。我在我的项目中应用了一个技巧。您可以做一件事,当您的应用程序启动时,检查“特定时间”是否已到。当设备“时区”或“时钟时间”发生变化时,您还需要检查它。

    func checkTimeToFireMethod(){
    
            let calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!
            let date = Date()
            calendar.locale = Locale(identifier: "en_US_POSIX")
            let hour = calendar.component(.hour, from: date)
            let minutes = calendar.component(.minute, from: date)
            let seconds = calendar.component(.second, from: date)
            let timeNowInSeconds = seconds + minutes*60 + hour*3600
            var timeLeft = 0
            // 6 am (06:00:00) changes to seconds (6*3600) and current time in seconds. here we are checking if the current time is less than 6:00:00 am
            if timeNowInSeconds < 6*3600{
                timeLeft = 6*3600 - timeNowInSeconds
            }
            // 6 pm (18:00:00) changes to seconds (18*3600) and current time in seconds. here we are checking if the current time is between  6:00:00 am and 6:00:00 pm.
            if timeNowInSeconds < 18*3600 && timeNowInSeconds >= 6*3600{
                 timeLeft = 18*3600 - timeNowInSeconds
    
            }
            // 6 pm (18:00:00) changes to seconds (18*3600) and current time in seconds. here we are checking if the current time is greater than  6:00:00 am and 6:00:00 pm.
            else if timeNowInSeconds >= 18*3600{
                timeLeft = 24*3600 - timeNowInSeconds
            }
    
            // to avoid any descripancy
            // check 30 seconds prior to actual time
            self.perform(#selector(self.myFuncation), with: nil, afterDelay: TimeInterval(timeLeft - 30))
            // check on time
            self.perform(#selector(self.myFuncation), with: nil, afterDelay: TimeInterval(timeLeft))
    
            // check 30 seconds after  actual time
            self.perform(#selector(self.myFuncation), with: nil, afterDelay: TimeInterval(timeLeft + 30))
        }
    

    然后调用你的函数来执行你的任务

    func myFuncation(){
    } 
    

    还添加以下通知:-

         NotificationCenter.default.addObserver(self, selector: #selector(self.checkTimeToFireMethod), name: NSNotification.Name.NSSystemClockDidChange, object: nil)
       NotificationCenter.default.addObserver(self, selector: #selector(self.checkTimeToFireMethod), name: NSNotification.Name.NSSystemTimeZoneDidChange, object: nil)
    

    【讨论】: