I inherited a code that is creating SwiftUI timer as below, inside a view
struct.
struct CustomButton: View {
...
private let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
...
And do not see any code to cancel the timer once the intended trigger is achieved and work is done.
But looking at the below guide I se that it is suggested to cancel the timer using timer.upstream.connect().cancel()
My question is how important is to cancel this timer, and I dont see any issues faced by the team till now but is this something that can cause any kind of issues? Or if the view gets released the timer will get released so this is not that important?
Reference: https://www.hackingwithswift.com/books/ios-swiftui/triggering-events-repeatedly-using-a-timer
let timer = Timer...
is actually not a good practice with SwiftUI and you could end up with memory leaks since SwiftUI can recreate the View at any time and create multiple timers.
The "best" way to handle animations and such is with TimelineView
TimelineView(.periodic(from: startDate, by: 1)) { context in
AnalogTimerView(date: context.date)
}
https://developer.apple.com/documentation/swiftui/timelineview
But if you have to use Timer
you should use it with onReceive
so it gets destroyed appropriately.
.onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect()) { output in
print("Timer called")
}
If you can also move into async/await and start using Task
as an alternative.
struct TimerSample: View {
@State private var isDisabled: Bool = true
var body: some View {
Button("Hello World!") {
}.disabled(isDisabled)
.task(id: isDisabled) {
guard isDisabled else {return}
try? await Task.sleep(for: .seconds(2))
isDisabled.toggle()
}
}
}