Прошу помощи. Создал приложение с таймером, но столкнулся с проблемой, что если пользователь выходит или переключается на другое приложение. Таймер просто останавливается. Как решить данную проблему ?
Работа таймера в фоновом режиме
-
Через некоторое время, приложение в бекграунде завершается.
-
Создать бэкграунд таск
let timer = NSTimer.scheduledTimerWithTimeInterval(N, target: self, selector: #selector(timerFunc(_:)), userInfo: nil, repeats: true)
…
func timerFunc(timer: NSTimer) {
//starts background task
let backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {}
…
//stops background task
if backgroundTask != UIBackgroundTaskInvalid {
if UIApplication.sharedApplication().applicationState == .Active {
UIApplication.sharedApplication().endBackgroundTask(backgroundTask!)
backgroundTask = UIBackgroundTaskInvalid
}
}
}
Это код swift 2.3, разберетесь?
Исправите ,если ошибся?)
let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(timerFunc), userInfo: nil, repeats: true)
func timerFunc(timer: Timer) {
var backgroundTask = UIApplication.shared.beginBackgroundTask {}
if backgroundTask != UIBackgroundTaskInvalid {
if UIApplication.shared.applicationState == .active {
UIApplication.shared.endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
P.S. скомпилил. Вроде как изначально все пошло хорошо , но при перезупуске в программу вселился дьявол. Ищу проблему
При включении приложения ,начинается отсчет со скоростью звука ,а когда время заканчивается и подъест звуковой сигнал включаются все звуки одновременно )
import UIKit
import AVFoundation
import AudioToolbox
class ViewController: UIViewController {
@IBOutlet weak var softboiledBt: UIButton!
@IBOutlet weak var inapounchBt: UIButton!
@IBOutlet weak var hardboiledBt: UIButton!
let softboiledConst = 240
let inapounchConst = 360
let hardboiledConst = 450
/*let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(timerFunc), userInfo: nil, repeats: true)*/
var selectedType = Array(repeating: false, count: 3)
var timery = Timer()
var isStarted = false
var counter: Int?
@IBAction func softboiledAction(_ sender: Any) {
if !isStarted {
selectedType[2] = false
selectedType[1] = false
selectedType[0] = true
setHighLightingForButtons()
refreshTimer()
}
}
@IBAction func inapounchAction(_ sender: Any) {
if !isStarted{
selectedType[2] = false
selectedType[1] = true
selectedType[0] = false
setHighLightingForButtons()
refreshTimer()
}
}
@IBAction func hardboiledAction(_ sender: Any) {
if !isStarted {
selectedType[2] = true
selectedType[1] = false
selectedType[0] = false
setHighLightingForButtons()
refreshTimer()
}
}
@IBOutlet weak var startbuttonoutlet: UIButton!
@IBAction func startbuttonAction(_ sender: Any) {
if !isStarted {
counter = getCurrentTimer()
timery.invalidate()
timery = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.timerAction), userInfo: nil, repeats: true)
startbuttonoutlet.setImage(#imageLiteral(resourceName: "stop"), for: UIControlState())
isStarted = true
disableButton ()
}else{
isStarted = false
timery.invalidate()
refreshTimer()
enableButton()
setHighLightingForButtons()
startbuttonoutlet.setImage(#imageLiteral(resourceName: "play-button"), for: UIControlState())
}
}
@IBOutlet weak var timerLabel: UILabel!
func timerAction() {
counter! -= 1
if counter! < 0 {
timerLabel.text = "Ready"
AudioServicesPlaySystemSound(SystemSoundID(1073))
AudioServicesPlaySystemSound(SystemSoundID(4095))
}else {
timerLabel.text = NSString (format: "%0.2d:%0.2d",counter!/60,counter!%60) as String
}
}
func refreshTimer() {
counter = getCurrentTimer()
timerLabel.text = NSString (format: "%0.2d:%0.2d",counter!/60,counter!%60) as String
}
func disableButton () {
softboiledBt.isEnabled = false
inapounchBt.isEnabled = false
hardboiledBt.isEnabled = false
}
func enableButton () {
softboiledBt.isEnabled = true
inapounchBt.isEnabled = true
hardboiledBt.isEnabled = true
}
/* func timerFunc(timer: Timer) {
var backgroundTask = UIApplication.shared.beginBackgroundTask {
//доделать
}
}
if backgroundTask != UIBackgroundTaskInvalid {
if UIApplication.shared.applicationState == .active {
UIApplication.shared.endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
}
}
}*/
override func viewDidLoad() {
super.viewDidLoad()
softboiledBt.isHighlighted = true
inapounchBt.isHighlighted = true
selectedType[2] = true
timerLabel.text = NSString(format: "%0.2d:%0.2d",hardboiledConst/60,hardboiledConst%60) as String
}
func getCurrentTimer() -> Int {
if selectedType [0] {
return softboiledConst
}
else if selectedType [1] {
return inapounchConst
} else{
return hardboiledConst
}
}
func setHighLightingForButtons() {
if selectedType[0]{
softboiledBt.isHighlighted = false
inapounchBt.isHighlighted = true
hardboiledBt.isHighlighted = true
}else if selectedType[1]{
softboiledBt.isHighlighted = true
inapounchBt.isHighlighted = false
hardboiledBt.isHighlighted = true
}else if selectedType[2]{
softboiledBt.isHighlighted = true
inapounchBt.isHighlighted = true
hardboiledBt.isHighlighted = false
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Без того ,что в комментариях работает ,вроде как ,корректно. Изначально подумал ,что налажал с секундами. Потом добавил функционал в таск ,но все вылетало после 10 секунд отсчета. Поэтому прокомментировал и дописал " доделать " (на будущее)
Сигнал один оставил еще
Скорее всего приложение вело себя так потому, что вы не туда вписали функционал:
/// таймер должен быть instance variable, если повторяется и не намерены делать timer.invalidate() в том же методе, в котором ег создали
var timer: Timer!
func timerFunc(timer: Timer) {
var backgroundTask = UIApplication.shared.beginBackgroundTask() /// кложур можно убрать, если вам не нужно обрабатывать expirationHandler
/// здесь пишется функционал бэкграунд таска
/// к примеру, выводить интервал таймера
print(timer.timeInterval.binade)
if backgroundTask != UIBackgroundTaskInvalid {
if UIApplication.shared.applicationState == .active {
UIApplication.shared.endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
softboiledBt.isHighlighted = true
inapounchBt.isHighlighted = true
selectedType[2] = true
timerLabel.text = NSString(format: "%0.2d:%0.2d",hardboiledConst/60,hardboiledConst%60) as String
/// измените интервал таймера на свое усмотрение
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerFunc), userInfo: nil, repeats: true)
}