【问题标题】:How to schedule a timer with initial delay?如何安排具有初始延迟的计时器?
【发布时间】:2018-12-26 07:30:35
【问题描述】:

在java中,我们可以创建一个具有初始延迟的周期性执行器,即延迟第一次执行的时间。这是一个例子:

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(new Fetcher(), 2, 10, TimeUnit.MINUTES);

class Fetcher implements Runnable {

    @Override
    public void run() {
        try {
              ...
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

例如,这个可运行文件在开始计划的两分钟后工作。然后它会每隔十分钟定期工作一次。

在 Swift 中,我们可以像下面这样安排一个计时器:

Timer.scheduledTimer(timeInterval: 120, target: self, selector: #selector(fetch(_:)), userInfo: nil, repeats: true)

@objc fileprivate func fetch(_ timer: Timer!) {
    ...
}

但是,我们如何为快速计时器设置初始延迟?

【问题讨论】:

    标签: java swift timer


    【解决方案1】:

    您需要 Timer 和初始化器中的参数 fireAt。当你想触发计时器时,fireAt 传递 Date

    let initialDelayInSeconds = 5
    let now = Date()
    let date = Calendar.current.date(bySettingHour: Calendar.current.component(.hour, from: now), minute: Calendar.current.component(.minute, from: now), second: Calendar.current.component(.second, from: now) + initialDelayInSeconds, of: now)!
    
    let timer = Timer(fireAt: date, interval: 120, target: self, selector: #selector(fetch(_:)), userInfo: nil, repeats: true)
    RunLoop.main.add(timer, forMode: .common) // don't forget to add `timer` to `RunLoop`
    

    【讨论】:

    • 好吧,我错过了那部分。它现在正在工作。我认为这是最好的解决方案。谢谢罗伯特!
    【解决方案2】:

    在大多数情况下,使用dispatch_after 块比使用sleep(time) 更好,因为执行睡眠的线程被阻止执行其他工作。当使用dispatch_after 时,正在处理的线程不会被阻塞,因此它可以同时进行其他工作。 如果您在应用程序的主线程上工作,则使用 sleep(time) 对应用程序的用户体验不利,因为在此期间 UI 没有响应。

    调度后调度代码块的执行而不是冻结线程:

    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(4), execute: {
    
            // Put your code which should be executed with a delay here
    
        })
    

    【讨论】:

    • 同样的问题。它只是推迟了创作。 4 分钟后,我的 fetcher 函数没有被调用。
    • 在调度中,您必须提及您的计时器将在多少秒后启动,并且计时器将花费时间来执行获取功能。
    【解决方案3】:

    您可以使用Timer,如下所示,

    Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
        Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(self.fetch(_:)), userInfo: nil, repeats: true)
    }
    

    或者DispatchQueue这样,

    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
        Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(self.fetch(_:)), userInfo: nil, repeats: true)
    }
    

    【讨论】:

    • 他们只是推迟了创作。 2 分钟后,我的 fetcher 函数没有被调用。
    • 谁知道fetcher是什么?
    • 创造了什么?请记住,您的 fetch 方法将在 initialTime + timerInterval 之后调用,即上述情况下的 (2+2),因此您必须等待这段时间。
    • 在 swift 中没有 fetcher。只有一个功能。获取()
    【解决方案4】:
    DispatchQueue.main.asyncAfter(deadline: .now() + 120, execute: {
           Timer.scheduledTimer(timeInterval:600, target: self, selector: #selector(fetch(_:)), userInfo: nil, repeats: true)
    })
    
    @objc fileprivate func fetch(_ timer: Timer!) {
    
    }
    

    【讨论】:

    • 这不起作用。 120 秒后,fetch 函数不会执行。它只是推迟了创作。
    • 它工作得很好。你可能做错了什么。
    • import UIKit import PlaygroundSupport PlaygroundPage.current.needsIndefiniteExecution = true class Abc { init() { print("init") DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: { print("main") Timer.scheduledTimer(timeInterval:10, target: self, selector: #selector(self.fetch), userInfo: nil, repeats: true) print("after timer") }) } @objc func fetch () { print("fetch") } } 让 a = Abc()
    • @Ahmet 这应该可以。您正在将fetcher 传递给Timer,但您有不同的方法,即fetch
    • 好的。它刚刚被修复。但这不起作用。在我的情况下,时间应该是:2、12、22、32。但在这种情况下:12、22、32 ...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    相关资源
    最近更新 更多