Why would a `scheduledTimer` fire properly when setup outside a block, but not within a block?
The issue is that the completion block in question was probably not running on the main thread and therefore didn't have a run loop. But timers need to be scheduled on a run loop, and while the main thread has one, most background threads do not (unless you add one, yourself).
To fix this, in that completion handler, dispatch the creation of the timer back to the main thread and it should work fine:
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(handleTimer(_:)), userInfo: nil, repeats: true)
}
Or use a dispatch source timer (a timer that can be scheduled for a background queue, and doesn't require a run loop).
var timer: DispatchSourceTimer!
private func startTimer() {
let queue = DispatchQueue(label: "com.domain.app.timer")
timer = DispatchSource.makeTimerSource(queue: queue)
timer.setEventHandler { [weak self] in
// do something
}
timer.schedule(deadline: .now(), repeating: 1.0)
timer.resume()
}
For syntax for earlier version of Swift, see previous revision of this answer.
Timer.scheduledTimer not firing
Your code works for me, but that isn't how you want to time an event because the Timer
isn't that accurate, and you are wasting a lot of computing time (read battery).
Instead, I suggest the following approach:
When the event starts, record the start time:
let startTime = Date()
When the event ends, compute the elapsed time:
let elapsedTime = Date().timeIntervalSince(startTime)
elapsedTime
will be in seconds (including fractional seconds).
Swift 3 Timer in a Class not firing
Change
msgTimer = Timer(timeInterval: 0.5, target: self, selector: #selector(typeMessage(_:)), userInfo: nil, repeats: true)
to
msgTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(typeMessage(_:)), userInfo: nil, repeats: true)
dismissViewControllerAnimated does not work within a block
In case someone is having the same issue. I pushed the UIViewController
, I didn't present it with presentViewController:animated:completion:
. That's why [self.navigationController popViewControllerAnimated:YES];
should be used instead.
The strange thing is that [self dismissViewControllerAnimated:YES completion:nil];
worked outside of the block and didn't inside, I have no explanation for this...
Use selector to call function with parameters
EDIT: Updating to include pre-iOS 10.0 solution
In this case it'd be better to use the scheduledTimer
function that takes a block, as this will allow you to pass arguments to your function:
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { (timer) in
SystemClass().setXYZ(xyz: 1.0)
}
For pre-iOS 10.0:
You can also pass userInfo in, including this default value, and then access that info from your inside your selector, like this:
Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(SystemClass().setXYZ(_:)), userInfo: 1.0, repeats: true)
To do this you'd also have to modify your setXYZ
function signature to look like this:
@objc func setXYZ(_ sender: Timer) {
if let xyz = sender.userInfo as? Float {
print(xyz)
// do something
}
}
swift invalidate timer doesn't work
The usual way to start and stop a timer safely is
var timer : Timer?
func startTimer()
{
if timer == nil {
timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)
}
}
func stopTimer()
{
timer?.invalidate()
timer = nil
}
startTimer()
starts the timer only if it's nil
and stopTimer()
stops it only if it's not nil
.
You have only to take care of stopping the timer before creating/starting a new one.
Related Topics
iOS Check If Application Has Access to Microphone
How to Find the Address of a Stack Trace in Lldb for iOS
Go VS. Return Button in iOS Keyboard for HTML Input Forms
How to Deserialize an Escaped JSON String with Nsjsonserialization
How to Identify iOS Device Uniquely
Swift iOS9 New Contacts Framework - How to Retrieve Only Cncontact That Has a Valid Email Address
Nsurlsessiondatatask Datataskwithurl Completion Handler Not Getting Called
Uilabel with Two Different Color Text
New Itunes Connect Interface -- Should It Immediately Be Seen on "Prerelease"
iOS Swift Navigate to Certain Viewcontroller Programmatically from Push Notification
Xcode Error While Validation - "Your Binary Is Not Optimized for iPhone 5"
Setting Up Uiscrollview to Swipe Between 3 View Controllers
Open Installed Pwa from External Url
Corebluetooth: What Is the Lifetime of Unique Uuids
Deferredlocationupdatesavailable Returns No in iOS 10
iOS Swift: How to Change the Font Style of a Certain Word in a String