Swift 3 - 如何让计时器在后台运行

Cri*_*yes 13 timer ios swift

我正在尝试做一个可以让计时器在后台运行的应用程序.

这是我的代码:

let taskManager = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(self.scheduleNotification), userInfo: nil, repeats: true)
        RunLoop.main.add(taskManager, forMode: RunLoopMode.commonModes)
Run Code Online (Sandbox Code Playgroud)

上面的代码将执行一个将调用本地通知的函数.当应用程序处于前台时,这是有效的,如何让它在后台运行?

我试图放几条打印线,我看到当我最小化(按下主页按钮)应用程序时,计时器停止,当我回到应用程序时,它恢复.

我希望计时器仍然在后台运行.有办法吗?

这就是我想要发生的事情:

运行应用程序 - >等待10秒 - >收到通知 - >等待10秒 - >收到通知 - >然后返回等待再次收到

在前景时发生.但不是在后台.请帮助.

Dar*_*ary 20

斯威夫特 4、斯威夫特 5

我更喜欢不在后台任务上运行计时器,只需比较 applicationDidEnterBackground 和 applicationWillEnterForeground 之间的日期秒数。

func setup() {
    NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground(_:)), name: UIApplication.didEnterBackgroundNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(applicationWillEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil)
}

@objc func applicationDidEnterBackground(_ notification: NotificationCenter) {
    appDidEnterBackgroundDate = Date()
}

@objc func applicationWillEnterForeground(_ notification: NotificationCenter) {
    guard let previousDate = appDidEnterBackgroundDate else { return }
    let calendar = Calendar.current
    let difference = calendar.dateComponents([.second], from: previousDate, to: Date())
    let seconds = difference.second!
    countTimer -= seconds
}
Run Code Online (Sandbox Code Playgroud)


Far*_*rzi 14

您可以转到功能并打开后台模式和活动音频.AirPlay,图片和图片.

真的行 .你不需要设置DispatchQueue.你可以使用Timer.

Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (t) in

   print("time")
}
Run Code Online (Sandbox Code Playgroud)

  • 不,我不需要播放声音。我有一个用于验证码的计时器。当我的应用程序进入后台时,我的计时器停止了。 (4认同)
  • 仔细研究其中的一些,已知苹果会拒绝出于其他目的滥用功能的应用程序。如果将您的应用设置为背景音频,则对更广泛的系统的音量设置等行为有影响。 (4认同)
  • 这根本没有回答问题。克里斯蒂娜问如何让它在后台工作,而你的代码没有这样做。它仅启动计时器并在前台时触发它。 (4认同)

Ari*_*gal 10

这有效。正如另一个答案中所建议的,它在异步任务中使用 while 循环,但它也包含在后台任务中

func executeAfterDelay(delay: TimeInterval, completion: @escaping(()->Void)){
    backgroundTaskId = UIApplication.shared.beginBackgroundTask(
        withName: "BackgroundSound",
        expirationHandler: {[weak self] in
            if let taskId = self?.backgroundTaskId{
                UIApplication.shared.endBackgroundTask(taskId)
            }
        })
    
    let startTime = Date()
    DispatchQueue.global(qos: .background).async {
        while Date().timeIntervalSince(startTime) < delay{
            Thread.sleep(forTimeInterval: 0.01)
        }
        DispatchQueue.main.async {[weak self] in
            completion()
            if let taskId = self?.backgroundTaskId{
                UIApplication.shared.endBackgroundTask(taskId)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


mat*_*att 7

只有满足以下两个条件时,计时器才能在后台运行:

  • 您的应用程序由于其他原因在后台运行.(大多数应用程序不会;大多数应用程序在进入后台时会被暂停.)并且:

  • 当应用程序进入后台时,计时器已经运行.

  • 根据我的经验,如果应用程序没有启动任何后台模式,`NSTimer` 将在应用程序进入后台时停止运行。但是当应用程序回到前台时,计时器可以继续运行,但会丢失在后台的时间间隔。 (13认同)

小智 3

计时器无法在后台运行。对于后台任务,您可以检查下面的链接...

https://www.raywenderlich.com/143128/background-modes-tutorial-getting-started