1 year ago
#355085
tHatpart
Working with Timers in SwiftUI table view
I am trying to have a live count down timer in my SwiftUI TableView, but it's currently not updating. I have done this in UIKit and trying a similar approach with SwiftUI's lifecycle, but currently not working. The implementation is showing a snapshot of the countdown for some cells, but not all, and it isn't a live countdown, meaning it'll show 17 minutes and 12 seconds, but it isn't changing to 11 seconds then 10 etc. But I can see from the print statement in the timer service class that the timeString
is updating. Not sure why this isn't working.
struct ListTakeCell: View {
@ObservedObject var presenter: TakeCellViewModel
var body: some View {
contentView
.foregroundColor(.white)
.cornerRadius(16)
.onAppear {
presenter.timerService.startTimer()
}
.onDisappear {
presenter.timerService.stopTimer()
}
}
var timerView: some View {
Text(presenter.timerService.timerString)
.padding(8)
.background(Color(UIColor.lightGray))
.foregroundColor(presenter.timerService.timerString == "Expired" ? .red : Color(UIColor.darkGray))
.cornerRadius(15)
}
}
In the view's viewModel I have the TimerService class like so:
@ObservedObject var timerService: TimerService
class TimerService: ObservableObject {
@Published var timerString = "loading"
private var timer = Timer()
private var targetDate: Date!
lazy var durationFormatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.day, .hour, .minute, .second]
formatter.unitsStyle = .abbreviated
return formatter
}()
init(expiresOn: Date) {
self.targetDate = expiresOn
startTimer()
}
deinit {
timer.invalidate()
}
func startTimer() {
self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerTicked(_:)), userInfo: nil, repeats: true)
}
func stopTimer() {
timer.invalidate()
}
@objc private func timerTicked(_ timer: Timer){
if targetDate.isEarlier(than: Date()){
timerString = "Expired"
return
}
guard let timeString = durationFormatter.string(from: targetDate.timeIntervalSince(Date())) else {return}
print("TIMER TICKED: \(timeString)")
self.timerString = timeString
}
}
class TakeCellViewModel: ObservableObject {
@Published var take: TakeOBJ!
@Published var authorName: NSAttributedString = NSAttributedString(string: "")
@Published var authorProfileImage: UIImage = UIImage.defaultAvatar
@ObservedObject var timerService: TimerService
init(take: TakeOBJ) {
self.take = take
timerService = TimerService(expiresOn: take.expiresOn.iso8601withFractionalSeconds ?? Date())
loadAuthor()
}
}
ios
swift
swiftui
observedobject
0 Answers
Your Answer