Timer.scheduledTimer Swift 3 pre-iOS 10 compatibility
Asked Answered
M

8

34

I need to schedule a Timer for firing a function every second but I see that in Xcode 8 beta 3 the scheduledTimer is only available for iOS 10.

Is there any alternative for using the timer in iOS 9 or previous versions?

Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { (timer) in print("Hi!")})
Myriammyriameter answered 1/8, 2016 at 9:50 Comment(0)
M
57

Solved using

Timer.scheduledTimer(timeInterval: 1,
                           target: self,
                         selector: #selector(self.updateTime),
                         userInfo: nil,
                          repeats: true)
Myriammyriameter answered 1/8, 2016 at 10:5 Comment(5)
If you wish you can use if #available(iOS 10, *) { //iOS 10 code } else { //iOS 9 code } to support both depending on the OS version.Zoometry
I needed to add write the target function like this: @objc func updateTime() {}Etter
It's also worth looking at the lower posts to see how Timer's are stopped. It may not get removed from the run loop properly if it's not removed manually.Electrode
Hy I am new to swift, just a basic question, what does userInfo represents in scheduledTimer function??Timpani
Hi @prasoonraj, I guess that it means that you can pass a dictionary with any useful information every time the timer is fired.Myriammyriameter
N
17

Run a timer with swift3,

var timer: Timer?

func startTimer() {

    if timer == nil {
        timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.loop), userInfo: nil, repeats: true)
    }
}

func stopTimer() {
    if timer != nil {
        timer?.invalidate()
        timer = nil
    }
}

func loop() {
    let liveInfoUrl = URL(string: "http://192.168.1.66/api/cloud/app/liveInfo/7777")
    let task = URLSession.shared.dataTask(with: liveInfoUrl! as URL) {data, response, error in
        guard let data = data, error == nil else { return }
        print(String(data: data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) ?? "aaaa")
    }
    task.resume()
}

Release the timer when you not use it.

Once scheduled on a run loop, the timer fires at the specified interval until it is invalidated. A nonrepeating timer invalidates itself immediately after it fires. However, for a repeating timer, you must invalidate the timer object yourself by calling its invalidate() method.

Negress answered 16/5, 2017 at 6:6 Comment(2)
Great job pointing out the .invalidate() end of Timer's, as well as the run loop.Electrode
The nil check for timer is unnecessary. It is already an optional.Tusk
I
8

Here is sample code workable with compatibility:

if #available(iOS 10.0, *) {
    Timer.scheduledTimer(withTimeInterval: 15.0, repeats: true){_ in
        // Your code is here:
        self.myMethod()
    }
} else {      
    Timer.scheduledTimer(timeInterval: 15.0, target: self, selector: #selector(self.myMethod), userInfo: nil, repeats: true)
}

//Your method or function:

// MARK: -  Method

@objc func myMethod() {
    print("Hi, How are you.")
}
Indira answered 1/3, 2018 at 10:56 Comment(0)
T
3

Swift 3

func runCode(in timeInterval:TimeInterval, _ code:@escaping ()->(Void))
{
    DispatchQueue.main.asyncAfter(
        deadline: .now() + timeInterval,
        execute: code)
}

func runCode(at date:Date, _ code:@escaping ()->(Void))
{
    let timeInterval = date.timeIntervalSinceNow
    runCode(in: timeInterval, code)
}

func test()
{
    runCode(at: Date(timeIntervalSinceNow:2))
    {
        print("Hello")
    }

    runCode(in: 3.0)
    {
        print("World)")
    }
}
Tamtam answered 3/2, 2017 at 22:58 Comment(0)
I
3

Updated for swift 3:

If you want to use Timer for some delay or any other purpose used below lines of code in your project;

// function defination:

func usedTimerForDelay()  {
    Timer.scheduledTimer(timeInterval: 0.3,
                         target: self,
                         selector: #selector(self.run(_:)),
                         userInfo: nil, 
                         repeats: false)
}

func run(_ timer: AnyObject) {
      print("Do your remaining stuff here...")

}

// function call:

self.usedTimerForDelay()

NOTE:- you can change the time interval as you want.

//Enjoy coding..!

Imitate answered 27/9, 2017 at 5:50 Comment(0)
C
1
Timer.scheduledTimer

Put it in the main thread.

Crider answered 12/5, 2018 at 9:3 Comment(0)
P
1

You can use the following simple shim to provide the new block-based Timers to pre-iOS 10:

class TimerShim {
    private var timer: Timer?
    private let block: (Timer) -> Void

    private init(timeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void) {
        self.block = block
        timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(timerDidFire), userInfo: nil, repeats: repeats)
    }

    class func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void) -> Timer {
        return TimerShim(timeInterval: interval, repeats: repeats, block: block).timer!
    }

    @objc private func timerDidFire() {
        block(timer!)
    }
}

Usage example:

TimerShim.scheduledTimer(withTimeInterval: 5, repeats: false) { _ in
    print("boom!")
}
Praemunire answered 2/6, 2020 at 10:48 Comment(0)
P
-5

The correct form is:

Timer.scheduledTimer(withTimeInterval: 2, repeats: false){_ in
   "Here your code method"
}
Powerdive answered 27/1, 2017 at 23:56 Comment(2)
This is not running on iOS 9, but the question asked for < iOS 10 compatibilityTamtam
This code is working on swift 4.2 also.. Thanx for it.Schwenk

© 2022 - 2024 — McMap. All rights reserved.