Live update relative time in SwiftUI

Viewed 2333

In my SwiftUI app, I'm showing relative time as follows.

struct ContentView: View {

    let date: Double = 1589014112

    var body: some View {
        Text(Date(timeIntervalSince1970: date).relativeTime())
    }
}

extension Date {
    func relativeTime(in locale: Locale = .current) -> String {
        let formatter = RelativeDateTimeFormatter()
        formatter.unitsStyle = .full
        return formatter.localizedString(for: self, relativeTo: Date())
    }
}

I get the time interval since 1970 as double from an API. I want to show relative time in my app. The output is as below.

enter image description here

The view updates only when I reload and it stays at "10 seconds ago" with every passing second. How to update it in real time? I want to change whenever the current date (Date()) changes.

2 Answers

You can use a TimerPublisher to trigger something periodically.
Here is a quick example below;

struct PlaygroundView: View {

    let timer = Timer.publish(
        every: 1, // second
        on: .main,
        in: .common
    ).autoconnect()

    let date = Date()

    @State var secondStr: String = ""

    var body: some View {
        Text(secondStr)
            .onReceive(timer) { (_) in
                self.secondStr = self.date.relativeTime()
            }
    }
}

extension Date {
    func relativeTime(in locale: Locale = .current) -> String {
        let formatter = RelativeDateTimeFormatter()
        formatter.unitsStyle = .full
        return formatter.localizedString(for: self, relativeTo: Date())
    }
}

You can observe that the secondStr changes every second like
1 seconds ago
2 seconds ago
and so on..

You can use SwiftUI Text's init(_:style:) to accomplish this without timers.

let date: Double = 1589014112

var body: some View {
    Text(Date(timeIntervalSince1970: date), style: .relative)
}

Note: The available styles should be enough for most use cases, but they are somewhat limited. See Text.DateStyle.

Related