I tried
Text(Date.now, format:
.relative(presentation: .named))
and also tried
Text(Date.now, style: .relative)
But the first one just says "now" even after 24 hours
and the second one is literally just a timer so instead of saying after one minute "1 minute ago" it says "1 minute, 20 seconds" for example. There aren't a lot of resources out there for this particular thing, so help will be appreciated
CodePudding user response:
Relative format presents date relatively to "now", it does not track time, we have to provide date explicitly, like
Text(Date().addingTimeInterval(-60), format:
.relative(presentation: .named))
rendered as
CodePudding user response:
The reason that your first one would stay saying "now", while the second one will update once a second is because:
The first one simply converts the input data to a string when the
Text
view is first created.The second one is a initializer that is specialized for
Date
. It actually creates a publisher behind the scene, that will update the underlying text once a second. However, as you might have found out already, only a fewDateStyle
were supported.
One solution is to create your own Date
wrapper class that conforms to ObservableObject
:
class PublishedDate: ObservableObject {
let date = Date.now
/// Manually creating a publisher that will emits once a second
var objectWillChange = Timer.publish(every: 1, on: .main, in:.common).autoconnect()
}
Now we can store our PublishedDate
in the view as a @StateObject
, and it will update relevant sub-views every time objectWillChange
fires:
struct ContentView: View {
@StateObject var date: PublishedDate = .init()
var body: some View {
VStack {
Text(date.date.formatted(.relative(presentation: .named)))
}
}
}