Stopping a SwiftUI Widget's relative textfield counter when hits zero?
Asked Answered
H

3

3

I am creating a Widget that has a textfield that counts down from a date like so:

Text(endDate, style: .relative)

This works fine, however as its relative, once it hits zero, it will continue to count back up again as the endDate becomes in the past.

Is there a way to terminate the text when it hits zero? Or do I have to rebuild this feature with a timer?

All I need to do is count down from a start date to and end date then invalidate the text field or show a message.

Honeysucker answered 29/10, 2020 at 16:53 Comment(1)
Does this answer your question https://mcmap.net/q/1483199/-how-to-stop-timer-in-text-view?Palmira
M
5

Here is how you can create a countdown and when the time is over display some other text.

  1. Create an Entry where endDate is optional - if it's nil it means that the countdown is over:
struct SimpleEntry: TimelineEntry {
    let date: Date
    var endDate: Date?
}
  1. In your Provider create two Entries - one for the countdown time and one for when the countdown is over:
struct SimpleProvider: TimelineProvider {
    ...

    func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
        let currentDate = Date()
        let endDate = Calendar.current.date(byAdding: .second, value: 15, to: currentDate)!

        let entries = [
            SimpleEntry(date: currentDate, endDate: endDate),
            SimpleEntry(date: endDate),
        ]

        let timeline = Timeline(entries: entries, policy: .never)
        completion(timeline)
    }
}
  1. Use it in your view:
struct WidgetEntryView: View {
    var entry: Provider.Entry

    var body: some View {
        if let endDate = entry.endDate {
            Text(endDate, style: .relative)
        } else {
            Text("Timer finished")
        }
    }
}
Maidenly answered 29/10, 2020 at 17:46 Comment(4)
thanks didnt know i could use entity like this, works great!Honeysucker
Sorry to bump, I have the same approach, however, widget is not refreshed on the specified date, but at a random offset that goes from 20s to 90s after the specified date. Any ideas why could that happen?Shroff
@Shroff the reason is probably because Apple doesn't guarantee it will update in the time you specified. They adapt update schedule for your widget constantly depending on how often the user is using the app, how often the app asks to get updated etcWench
Yes, but I am trying on my personal phone with developer mode enabled for WidgetKit, so these restrictions do not apply yetShroff
R
1

Since iOS 16, it is now possible to stop at 0 by setting the 'countsDown' argument of Text to true.

https://developer.apple.com/documentation/swiftui/text/init(timerinterval:pausetime:countsdown:showshours:)

Rascality answered 13/12, 2023 at 10:40 Comment(1)
You mean by setting the pauseTime argument to the Date at which you want to stop, right? So if countsDown is true, pass pauseTime: timerInterval.lowerBound, otherwise upperBound. countsDown simply controls whether the timer is incrementing or decrementing - to stop it at 0, you need to pass a pauseTime.Entirety
W
0

I think you have to schedule a widget update at time zero and have conditions to hide it when less than zero.

Whiteness answered 29/10, 2020 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.