Таймер останавливается, когда телефон переходит в режим полета, не будет перезапущен после выхода из AM - PullRequest
0 голосов
/ 16 ноября 2018

OK. Посмотрел возможные ответы, но я не вижу здесь своей проблемы.

У меня довольно многообещающий таймер GCD:

class RepeatingGCDTimer {
    /// This holds our current run state.
    private var state: _State = ._suspended

    /// This is the time between fires, in seconds.
    let timeInterval: TimeInterval
    /// This is the callback event handler we registered.
    var eventHandler: (() -> Void)?

    /* ############################################################## */
    /**
     This calculated property will create a new timer that repeats.

     It uses the current queue.
     */
    private lazy var timer: DispatchSourceTimer = {
        let t = DispatchSource.makeTimerSource()    // We make a generic, default timer source. No frou-frou.
        t.schedule(deadline: .now() + self.timeInterval, repeating: self.timeInterval)  // We tell it to repeat at our interval.
        t.setEventHandler(handler: { [unowned self] in  // This is the callback.
            self.eventHandler?()    // This just calls the event handler we registered.
        })
        return t
    }()

    /// This is used to hold state flags for internal use.
    private enum _State {
        /// The timer is currently paused.
        case _suspended
        /// The timer has been resumed, and is firing.
        case _resumed
    }

    /* ############################################################## */
    /**
     Default constructor

     - parameter timeInterval: The time (in seconds) between fires.
     */
    init(timeInterval inTimeInterval: TimeInterval) {
        self.timeInterval = inTimeInterval
    }

    /* ############################################################## */
    /**
     If the timer is not currently running, we resume. If running, nothing happens.
     */
    func resume() {
        if self.state == ._resumed {
            return
        }
        self.state = ._resumed
        self.timer.resume()
    }

    /* ############################################################## */
    /**
     If the timer is currently running, we suspend. If not running, nothing happens.
     */
    func suspend() {
        if self.state == ._suspended {
            return
        }
        self.state = ._suspended
        self.timer.suspend()
    }

    /* ############################################################## */
    /**
     We have to carefully dismantle this, as we can end up with crashes if we don't clean up properly.
     */
    deinit {
        self.timer.setEventHandler {}
        self.timer.cancel()
        self.resume()   // You need to call resume after canceling. I guess it lets the queue clean up.
        self.eventHandler = nil
    }
}

Отлично работает!

... кроме случаев, когда это не так.

Это было бы, когда я переводил устройство в режим полета.

В этот момент таймер прекращает работу.

Даже когда я выхожу из режима полета, таймер не перезапускается.

Приложение использует UIApplication.shared.isIdleTimerDisabled = true / false, чтобы держать приложение в активном состоянии, но, похоже, не заставляет события наступать.

Может кто-нибудь подсказать мне, что здесь происходит, и как я мог бы обойти это?

Это приложение должно работать в режиме полета. Фактически, он, скорее всего, будет использоваться в режиме полета.

1 Ответ

0 голосов
/ 16 ноября 2018

OK.Я думаю, что я решил это.Как это часто бывает с этими вещами, это PEBCAK.

У меня есть подпрограмма, которая останавливает таймер, когда приложение установлено на заднем плане, и не может выполнить соответствующий перезапуск, если оно установлено на заднем плане.

Когда я двигаюсь вверх по Центру управления, это заставляет работать приложение.

Мой плохой.

Да, это неловко, но я хочу оставить этот вопрос здесь как предупреждение для других.

...