I am making an attempt to make a easy timer in a LiveActivity on iOS however I preserve having some points with a format once I use Textual content(timerInterval:) answer.
- If I exploit Textual content(timerInterval:) that is the way it seems to be within the Dynamic Island and Lock Display
- If I exploit a easy calculation it seems to be good in format nevertheless it doesn’t replace the counting.
What could possibly be mistaken? I attempted to observe the easy timer tutorials however i am unable to discover the difficulty.
PD: I am not an iOS dev 🙂
That is the LiveActivity lockScreen part and Attributes
struct TimerAttributes: ActivityAttributes {
public typealias TimerStatus = ContentState
public struct ContentState: Codable, Hashable {
// Solely changeable state goes right here
var isPaused: Bool
var isCompleted: Bool = false
// Show information
var taskTitle: String
var taskColor: String // Shade as hex string for serialization
// Word: These features now must be referred to as with attributes parameter
func getRemainingTime(endDate: Date, at date: Date = Date()) -> TimeInterval {
if isCompleted {
return 0
}
return max(0, endDate.timeIntervalSince(date))
}
func getElapsedTime(startDate: Date, at date: Date = Date()) -> TimeInterval {
return max(0, date.timeIntervalSince(startDate))
}
func isTimerRunning(endDate: Date, at date: Date = Date()) -> Bool {
return !isPaused && !isCompleted && getRemainingTime(endDate: endDate, at: date) > 0
}
// Helper strategies matching the working SimpleTimer strategy
func getElapsedTimeInSeconds(startDate: Date) -> TimeInterval {
return Date().timeIntervalSince(startDate)
}
func getFormattedElapsedTime(startDate: Date) -> String {
let elapsed = getElapsedTimeInSeconds(startDate: startDate)
let totalSeconds = Int(elapsed)
let hours = totalSeconds / 3600
let minutes = (totalSeconds % 3600) / 60
let seconds = totalSeconds % 60
if hours > 0 {
return String(format: "%d:%02d:%02d", hours, minutes, seconds)
} else {
return String(format: "%d:%02d", minutes, seconds)
}
}
func getFutureDate() -> Date {
return Date().addingTimeInterval(365 * 24 * 60 * 60)
}
}
// Static content material that does not change in the course of the exercise
var taskId: String
var startDate: Date
var endDate: Date
var countsDown: Bool // true for timer mode
}
@ViewBuilder
func lockScreenView(context: ActivityViewContext<TimerAttributes>) -> some View {
HStack {
// Left aspect - Icon and timer
VStack(alignment: .main, spacing: 4) {
HStack(spacing: 8) {
Picture(systemName: "timer")
.foregroundColor(Shade(hex: context.state.taskColor) ?? .orange)
.font(.title3)
if isTimerCompleted(context: context) {
Textual content("Carried out!")
.font(.system(measurement: 16, weight: .semibold))
.foregroundColor(.inexperienced)
} else if context.state.isPaused {
Textual content("Paused")
.font(.system(measurement: 16, weight: .semibold))
.foregroundColor(Shade(hex: context.state.taskColor) ?? .orange)
} else {
Textual content(timerInterval: Date()...context.attributes.endDate, countsDown: true)
.font(.system(measurement: 16, weight: .semibold))
.foregroundColor(Shade(hex: context.state.taskColor) ?? .orange)
.monospacedDigit()
}
}
Textual content(context.state.isPaused ? "Timer Paused" : "Timer Lively")
.font(.caption)
.foregroundColor(.secondary)
}
Spacer()
// Proper aspect - Activity title
VStack(alignment: .trailing, spacing: 4) {
Textual content(context.state.taskTitle)
.font(.headline)
.fontWeight(.semibold)
.multilineTextAlignment(.trailing)
.lineLimit(2)
.foregroundColor(.white)
Textual content("(Int(calculateProgress(attributes: context.attributes, state: context.state) * 100))% Full")
.font(.caption)
.foregroundColor(.secondary)
}
}
.padding(16)
}