I too have been searching for a way to get a timer to show within a Live Activity view in a format like 3m or 3min as is shown in the Apple Documentation.
From what I've found so far, the new TImeDataSource available in iOS 18 gets closest:
Text(TimeDataSource<Date>.durationOffset(to: startDate), format: .units(allowed: [.hours, .minutes], width: .narrow, fractionalPart: .hide(rounded: .down)))
This creates an updating Duration based on the difference between the current time and the offset date and will work within a LiveActivity view (mostly**).
This example formatting displays a timer that counts up from your startDate Date in Xm format. When reaching an hour, it would shift to Xh and subsequently Xh Xm.
There's a helpful resource created here that outlines FormatStyle options:
https://goshdarnformatstyle.com/duration-styles/
**Within a regular app view, the timer value updates as expected...at the top of a new minute. However, I notice that the values seem to update inconsistently within a LiveActivity view like the Dynamic Island. If anyone has a fix for that, I'd love to see it.
Other unsolved challenges:
Because this requires TimeDataSource, it will not work with earlier iOS versions--I have not found an alternative there.
The width of the generated Text frame is huge which creates a challenge, especially in compact Dynamic lsland views. The only way I've found to fit the timer is to use the TimeDataSource as an overlay above a hidden Text view. Unfortunately this approach makes it hard coded to a defined width so you either need to set your hidden Text to be the maximum potential timer width or push updates to redraw the Live Activity at key increments (e.g. 9m -> 10m, 60m to 1h, etc.)
Text("0m")
.hidden()
.overlay(alignment: .leading) {
Text(TimeDataSource<Date>.durationOffset(to: startDate), format: xxxxx)
}
You can use this to format a countdown timer to a future date, but there's seemingly no way to remove the preceding negative sign within FormatStyle. The example below would show a countdown timer in Xh Xm format, but always with a negative sign.
Text(TimeDataSource<Date>.durationOffset(to: futureDate), format: .units(allowed: [ .minutes, .hours], width: .narrow, maximumUnitCount: 2, zeroValueUnits: .show(length: 1), valueLengthLimits: 2...3))
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags: