【发布时间】:2018-03-10 12:12:08
【问题描述】:
我正在开发冥想应用程序。在这个应用程序中,我有一些音乐内容和一些使用计时器的无声冥想部分。定时器在前台工作正常,但在后台仅运行 3 分钟(当设备被锁定或用户按下主页按钮退出应用程序时)。我正在使用 swift4。我尝试过的:
var timer: Timer!
var timeCounter : Int!
var backgroundTaskIdentifier: UIBackgroundTaskIdentifier?
var backgroundTask = BackgroundTask()
@IBOutlet weak var timeLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: {
UIApplication.shared.endBackgroundTask(self.backgroundTaskIdentifier!)
})
backgroundTask.startBackgroundTask()
DispatchQueue.global(qos: .background).async {
let currentRunLoop = RunLoop.current
let timeInterval = 1.0
self.timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(self.updateTimer), userInfo: nil, repeats: true)
self.timer.tolerance = timeInterval * 0.1
currentRunLoop.add(self.timer, forMode: .commonModes)
currentRunLoop.run()
}
}
}
@objc func updateTimer () {
timeCounter = timeCounter - 1
let minutes = Int(timeCounter) / 60 % 60
let seconds = Int(timeCounter) % 60
print("timeCounter", timeCounter)
if (timeCounter == 0){
if self.timer != nil {
self.timer?.invalidate()
self.timer = nil
player.play()
}
}
timeLabel.fadeTransition(0.4)
timeLabel.text = String(format: "%02i:%02i",minutes,seconds)
}
提前致谢。
【问题讨论】:
-
这不是您想要的方法。计时器不在后台运行。 (而且你几乎不应该打电话给
runloop.run();这是一件非常高级的事情。)当你完成后你没有正确地结束你的后台任务(你只在过期时才这样做,这不是一个好习惯。 ) 精确的解决方案将取决于您正在做什么。您可能想成为一个音乐应用程序并利用它来驱动其他一切。您可能需要考虑静音音频(这对电池有些不利,但可能是这种用户体验的理想选择)。您还可以查看 UserNotifications 来计时。 -
鉴于您到目前为止所描述的,我认为您确实可以使用标准工具构建一些非常好的东西。 NSTimer 不是正确的,它完全取决于您想要的用户体验。
-
感谢@RobNapier 的回复......我该如何解决这个问题?对于这种情况,您建议哪种最佳解决方案。所以当用户锁定设备屏幕时,我可以长时间播放计时器。
-
解决这个问题很大程度上取决于你的用例;当您播放音频以及绝对必须运行代码时。您所描述的可以通过成为一个后台应用程序来完成,当您想要保持静音时播放静音音频(这将是最直接的)。见developer.apple.com/library/content/documentation/iPhone/… 和developer.apple.com/library/content/documentation/Audio/…
-
@RobNapier:Apple 不会批准使用此技巧的应用程序(如果他们发现):“在后台播放音频内容的应用程序必须播放有声内容而不是静音。”
标签: ios swift nstimer background-process