All, I am trying to setup a timer to start at a given time and then repeat at intervals. The Timer.init(fireAt:... initializer seems to fit this, but is giving me an "Unexpectedly found nil while unwrapping an Optional value" on @main.
Here is my code
import SwiftUI
class testout {
@objc func timerTesting() {
print("Test")
}
}
@main
struct My_MacOS_SandboxApp: App {
var body: some Scene {
WindowGroup {
TimerStartAt0Mins()
}
}
}
struct TimerStartAt0Mins: View {
@State private var testTimer = Timer()
var myOut = testout()
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
.onAppear {
print("now = \(Date.now.formatted())")
let nowplus10 = Date.now.addingTimeInterval(10)
print("now+10 = \(nowplus10.formatted())")
myOut.timerTesting()
testTimer = Timer.init(fireAt: nowplus10, interval: 60, target: self, selector: #selector(myOut.timerTesting), userInfo: nil, repeats: true)
}
}
}
and the full error is: My MacOS Sandbox[17252:1206390] Swift/RangeReplaceableCollection.swift:625: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Any help would be appreciated.
Thanks to both of the responders - although neither was an actual solution to what I was wanting to do, they did give me inspiration on what to be researching. It turns out, that I was using the wrong Timer.init function. I couldn't get #selector's to work in the fireAt: init - so I used the one with a block:. I also found that the Timer is not always guaranteed to fire at the specified time (+/- a sec sometimes) so using interval: would eventually throw my needed timing off completely.
So, here is what I ended up with to get a func to run at the start (0 secs) of each minute...
struct TimerStartAt0Secs: View {
@State private var testTimer: Timer?
var body: some View {
Text("Hello, World!")
.onAppear {
print("now = \(Date.now.formatted(date: .omitted, time: .complete))")
fireAtStartOfNextMin()
}
}
func fireAtStartOfNextMin() {
let calendar = Calendar.current
var timerStartComponents = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second, .timeZone], from: Date.now)
timerStartComponents.minute! += 1
timerStartComponents.second = 0
let timerStart = calendar.date(from: timerStartComponents)
testTimer = Timer.init(fire: timerStart!, interval: 0, repeats: false, block: { _ in
print("Test \(Date.now.formatted(date: .omitted, time: .complete))")
fireAtStartOfNextMin()
})
RunLoop.main.add(testTimer!, forMode: RunLoop.Mode.common)
}
}