Bijington Bijington - 1 year ago 57
Swift Question

Timer not firing (timeInterval always == 0.0)

I have created a

Timer
inside a singleton and I have been fighting with why the
Timer
is not firing. I have looked over posts on here but I have not found one that I believe directly answers my issue.

class ConnectionStateMonitor : NSObject {
static let shared = ConnectionStateMonitor()

var isConnected = false

fileprivate let reachability = Reachability()!
fileprivate var reconnectTimer: Timer?
fileprivate var reconnectPollInterval = TimeInterval(10.0)

func initialise() {
reachability.stopNotifier()

reachability.whenReachable = { reachability in

if reachability.isReachableViaWiFi {
Log.debug(message: "Reachable via WiFi")
} else {
Log.debug(message: "Reachable via Cellular")
}

self.updateConnectionState(isConnected: true)
}
reachability.whenUnreachable = { reachability in
Log.debug(message: "Not reachable")

self.updateConnectionState(isConnected: false)
}

do {
try reachability.startNotifier()
} catch {
//print("Unable to start notifier")
}
}

func updateConnectionState(isConnected: Bool) {
let wasConnected = self.isConnected

Log.debug(message: "Update connection state: \(isConnected)")

synchronize(lockObj: self, closure: {
self.isConnected = isConnected
})

self.updateReconnectTimer()
}

fileprivate func updateReconnectTimer() {
// Suspend any pending call.
self.reconnectTimer?.invalidate()

if !self.isConnected {
self.reconnectTimer = Timer.scheduledTimer(timeInterval: self.reconnectPollInterval, target: self, selector: #selector(ConnectionStateMonitor.attemptReconnect), userInfo: nil, repeats: false)
// Uncommenting below fires the timer.
//self.reconnectTimer?.fire()


print("attempting to reconnect in self.reconnectPollInterval = \(self.reconnectPollInterval) \(self.reconnectTimer?.timeInterval)s")
}
else {
self.reconnectTimer = nil
}
}

@objc func attemptReconnect() {
print("attempting to reconnect")

self.comms?.hello(completionHandler: { success, message in
self.updateReconnectTimer()
})
}
}


The print statement inside updateReconnectTimer prints out:

attempting to reconnect in self.reconnectPollInterval = 10.0 Optional(0.0)s

I can't for the life of me work out why the timeInterval property of my
Timer
would be 0.0 when I explicitly set it to 10.0. Calling
fire
correctly calls my function so I know that it is hooked up correctly.

Also to confirm there are no subsequent calls to the updateReconnectTimer function that would interfere.

Is there anything obvious that I am missing?

EDIT:

I have added in more code to show the issue, it appears that by updating the
Timer
in the completion handlers from
Reachability
which will be a background thread seems to prevent the
Timer
from firing.

Answer Source

Unfortunately the bug appeared to be relating to the fact that I was updating the reconnectTimer field on different threads. Forcing it to be updated on the same thread each time corrected the issue.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download