I tried
var timer = NSTimer()
timer(timeInterval: 0.01, target: self, selector: update, userInfo: nil, repeats: false)
But, I got an error saying
'(timeInterval: $T1, target: ViewController, selector: () -> (), userInfo: NilType, repeats: Bool) -> $T6' is not identical to 'NSTimer'
This question is related to
ios
nstimer
nstimeinterval
swift
NSTimer has been renamed to Timer in Swift 4.2. this syntax will work in 4.2:
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)
for swift 3 and Xcode 8.2 (nice to have blocks, but if You compile for iOS9 AND want userInfo):
...
self.timer = Timer(fireAt: fire,
interval: deltaT,
target: self,
selector: #selector(timerCallBack(timer:)),
userInfo: ["custom":"data"],
repeats: true)
RunLoop.main.add(self.timer!, forMode: RunLoopMode.commonModes)
self.timer!.fire()
}
func timerCallBack(timer: Timer!){
let info = timer.userInfo
print(info)
}
As of iOS 10 there is also a new block based Timer factory method which is cleaner than using the selector:
_ = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { timer in
label.isHidden = true
}
Swift 5
I personally prefer the Timer with the block closure:
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
// TODO: - whatever you want
}
First declare your timer
var timer: Timer?
Then add line in viewDidLoad() or in any function you want to start the timer
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(action), userInfo: nil, repeats: false)
This is the func you will callback it to do something it must be @objc
@objc func action () {
print("done")
}
This is a simple timer class in swift that enables you to:
SimpleTimer(interval: 3,repeats: true){print("tick")}.start()//Ticks every 3 secs
class SimpleTimer {/*<--was named Timer, but since swift 3, NSTimer is now Timer*/
typealias Tick = ()->Void
var timer:Timer?
var interval:TimeInterval /*in seconds*/
var repeats:Bool
var tick:Tick
init( interval:TimeInterval, repeats:Bool = false, onTick:@escaping Tick){
self.interval = interval
self.repeats = repeats
self.tick = onTick
}
func start(){
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(update), userInfo: nil, repeats: true)//swift 3 upgrade
}
func stop(){
if(timer != nil){timer!.invalidate()}
}
/**
* This method must be in the public or scope
*/
@objc func update() {
tick()
}
}
Updated to Swift 4, leveraging userInfo:
class TimerSample {
var timer: Timer?
func startTimer() {
timer = Timer.scheduledTimer(timeInterval: 5.0,
target: self,
selector: #selector(eventWith(timer:)),
userInfo: [ "foo" : "bar" ],
repeats: true)
}
// Timer expects @objc selector
@objc func eventWith(timer: Timer!) {
let info = timer.userInfo as Any
print(info)
}
}
Check with:
Swift 2
var timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: Selector("update"), userInfo: nil, repeats: true)
Swift 3, 4, 5
var timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
Swift 3, pre iOS 10
func schedule() {
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 20, target: self,
selector: #selector(self.timerDidFire(timer:)), userInfo: nil, repeats: false)
}
}
@objc private func timerDidFire(timer: Timer) {
print(timer)
}
Swift 3, iOS 10+
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(withTimeInterval: 20, repeats: false) { timer in
print(timer)
}
}
Notes
@objc
You can use a timer to do an action multiple times, as seen in the following example. The timer calls a method to update a label every half second.
Here is the code for that:
import UIKit
class ViewController: UIViewController {
var counter = 0
var timer = Timer()
@IBOutlet weak var label: UILabel!
// start timer
@IBAction func startTimerButtonTapped(sender: UIButton) {
timer.invalidate() // just in case this button is tapped multiple times
// start the timer
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
}
// stop timer
@IBAction func cancelTimerButtonTapped(sender: UIButton) {
timer.invalidate()
}
// called every time interval from the timer
func timerAction() {
counter += 1
label.text = "\(counter)"
}
}
You can also use a timer to schedule a one time event for some time in the future. The main difference from the above example is that you use repeats: false
instead of true
.
timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)
The above example calls a method named delayedAction
two seconds after the timer is set. It is not repeated, but you can still call timer.invalidate()
if you need to cancel the event before it ever happens.
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
And Create Fun By The Name createEnemy
fund createEnemy ()
{
do anything ////
}
You will need to use Timer instead of NSTimer in Swift 3.
Here is an example:
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(YourController.update),
userInfo: nil,
repeats: true)
// @objc selector expected for Timer
@objc func update() {
// do what should happen when timer triggers an event
}
In Swift 3 something like this with @objc:
func startTimerForResendingCode() {
let timerIntervalForResendingCode = TimeInterval(60)
Timer.scheduledTimer(timeInterval: timerIntervalForResendingCode,
target: self,
selector: #selector(timerEndedUp),
userInfo: nil,
repeats: false)
}
@objc func timerEndedUp() {
output?.timerHasFinishedAndCodeMayBeResended()
}
If you init method of timer
let timer = Timer(timeInterval: 3, target: self, selector: #selector(update(_:)), userInfo: [key : value], repeats: false)
func update(_ timer : Timer) {
}
then add it to loop using method other selector will not be called
RunLoop.main.add(timer!, forMode: .defaultRunLoopMode)
NOTE : If you are want this to repeat make repeats true and keep the reference of timer otherwise update method will not be called.
If you are using this method.
Timer.scheduledTimer(timeInterval: seconds, target: self, selector: #selector(update(_:)), userInfo: nil, repeats: true)
keep a reference for later use if repeats is true.
I tried to do in a NSObject Class and this worked for me:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
print("Bang!") }
Source: Stackoverflow.com