Основная утилита таймеров GCD по сравнению со стандартными таймерами заключается в том, что они могут работать в фоновой очереди. Как сказал Аспери, вы можете отправлять обновления в основную очередь, если ваш таймер GCD сам не использует основную очередь.
Но вы также можете просто запланировать таймер GCD в главной очереди из get go, и тогда вам вообще не нужно вручную отправлять в главную очередь:
let timer = DispatchSource.makeTimerSource(queue: .main)
Но, если вы собираетесь запустить это в основном потоке, вы можете просто использовать Timer
, или, в проектах SwiftUI, вы можете предпочесть Combine TimerPublisher
:
import Combine
...
var timer: AnyCancellable? = nil
timer = Timer.publish(every: 1, on: .main, in: .common)
.autoconnect()
.sink { _ in
let remaining = start.addingTimeInterval(seconds).timeIntervalSince(Date())
guard remaining >= 0 else {
viewData.timeRemaining = "done!"
timer?.cancel()
return
}
let mins = Int(remaining / 60.0)
let secs = Int(remaining) % 60
viewData.timeRemaining = timeRemaining(minutes: mins, seconds: secs)
}
Когда вы включаете свой таймер в свой код SwiftUI (а не глобальный, как здесь), приятно оставаться в парадигме Combine Publisher
.
Я также думаю, что это возможно, лучше отменить таймер, когда он истекает в обработчике таймера, вместо того, чтобы делать отдельный asyncAfter
.
Не связанный, но вы можете рассмотреть возможность использования DateComponentsFormatter
в вашей функции timeRemaining
, например :
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.minute, .second]
formatter.unitsStyle = .full
return formatter
}()
func timeRemaining(_ timeInterval: TimeInterval) -> String {
formatter.string(from: timeInterval) ?? "Error"
}
Тогда
- Это избавит вас от необходимости вычислять минуты и секунды самостоятельно;
- Строка будет локализована; и
- Это обеспечит грамматически правильную формулировку; например, когда осталось 61 секунда, и существующая процедура выдаст грамматически неверное сообщение «1 минута 1 секунда».
DateComponentsFormatter
избавляет вас от трудностей, связанных с такими крайними случаями, когда вы хотите использовать единственное число вместо множественного числа или языки, отличные от Engli sh.