iOS Swift Timer не запускается, если приложение находится в фоновом режиме

Я занимаюсь разработкой библиотеки Cocoapod, в которой мне нужно вызывать функцию при срабатывании таймера. Я использую этот Cocoapod в приложении для iOS, таймер не срабатывает, когда приложение переходит в фоновое состояние

private var timer : DispatchSourceTimer? = nil

let queue = DispatchQueue(label: "sample.timer")
timer = DispatchSource.makeTimerSource(queue : queue)
timer?.setEventHandler 
{
    [weak self] in
    self?.sendData()
}
timer?.scheduleRepeating(deadline: .now(), interval: .seconds(5))

3 ответа

Тот факт, что вы используете GCD таймер (альтернатива Timerкоторый может работать в фоновых потоках) заставляет задуматься, не смешиваете ли вы два совершенно разных использования слова "фон":

  • Одно значение "фон" связано с фоновыми очередями или потоками во время работы приложения. Это в отличие от "основного" потока / очереди.

    И да, таймеры GCD отличаются от Timer экземпляры, поскольку они могут работать в фоновых очередях (при условии, что само приложение действительно работает).

  • Другое значение "фон" связано с состоянием приложения. Вы можете либо работать на переднем плане, работать на заднем плане, либо быть приостановленным / прекращенным.

    Во время работы приложения (на переднем или на заднем плане), таймеры (таймеры GCD или стандартные Timer) может работать. Но если приложение приостановлено или прекращено, все выполнение будет остановлено, включая таймеры.

Проблема в том, что вы пытаетесь запустить таймер, пока само приложение было приостановлено. Это не будет работать.

Ваше приложение не будет работать в фоновом режиме, если вы не:

  • попросить немного времени для выполнения некоторой задачи конечной длины (которая, IIRC, выполняется только в течение 3 минут); или же

  • В вашем приложении включен некоторый фоновый режим для определенных утвержденных целей (например, навигация, музыка, VOIP и т. д.).

Но приложения не могут продолжать работать в фоновом режиме (таймеры или что-то еще), за исключением тех особых узких ситуаций. Для получения дополнительной информации о фоновом выполнении см. Руководство по программированию приложения для iOS: Фоновое выполнение.

Попробуйте этот код, он работает нормально.

Timer.scheduledTimer(timeInterval: 5, target: self,   selector: (#selector(self.callTimerFunction)), userInfo: nil, repeats: false)

func callTimerFunction() {
    print("Hi.")
}

Это немного странно, но вы можете попытаться ограничить свое время в фоновом режиме и обойти эту проблему.

import AVFoundation

do {
    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord, with: .mixWithOthers)
    try AVAudioSession.sharedInstance().setActive(true)
}
catch { print(error) }
Другие вопросы по тегам