1

Let's say I have a view controller with code that I want to execute at a certain time, say 2:00pm. What I want to happen is that if the user opens the view controller at 1:58pm, that the code will wait and continuously check the time, executing itself at exactly 2:00pm. Is there a way to do this in Swift 4, perhaps with a timer?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
ch1maera
  • 1,369
  • 5
  • 20
  • 42

4 Answers4

2

You can figure out the number of seconds between your future date and now and use either GCD or Timer to setup your future event:

let futureDate = ISO8601DateFormatter().date(from: "2018-1-1T00:00:00Z" )!
DispatchQueue.main.asyncAfter(deadline: .now() + futureDate.timeIntervalSinceNow) {
    print("Its the future!")
}

or

let futureDate = ISO8601DateFormatter().date(from: "2018-1-1T00:00:00Z" )!
let timer = Timer.scheduledTimer(withTimeInterval: futureDate.timeIntervalSinceNow, repeats: false) {
    print("Its the future!")
}

Timer is easier to cancel and reschedule:

timer.invalidate()
Josh Homann
  • 15,933
  • 3
  • 30
  • 33
2

You can go around this way to achieve the result:

 override func viewDidLoad() {
     super.viewDidLoad()
     let dateFormatter = DateFormatter()
     /*The accepted DateFormat*/
     dateFormatter.dateFormat = "MM-dd-yyyy HH:mm"
     /*My Date String to run the code at*/
     let dateString = "12-06-2017 15:41"
        let date = dateFormatter.date(from: dateString)

        /*Now find the time differnce from now*/
        let secondsFromNowToFinish = date?.timeIntervalSinceNow

        DispatchQueue.main.asyncAfter(deadline: .now() + secondsFromNowToFinish!, execute: {

            print ("Hello Future.")
        })


    }

Tested and running. enter image description here

References:

DateFormatter

Convert Date String to Date

Happy coding. Hope it helps. Please remove the forced unwrappings.

Md. Ibrahim Hassan
  • 5,359
  • 1
  • 25
  • 45
1

You can add a timer with a fire date to the runloop:

{
    let dateOfExecution = Date(timeIntervalSince1970: <number of seconds from 1970-01-01-00:00:00 to your date of execution>)
    let timer = Timer(fireAt: dateOfExecution, interval: 0, target: self, selector: #selector(codeToExecute), userInfo: nil, repeats: false)
    RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)
}

@objc func codeToExecute() {
    <Your code to run> 
}

See Apple docs: https://developer.apple.com/documentation/foundation/timer/1415700-init

Nicolas Buquet
  • 3,880
  • 28
  • 28
-1

Read about DispatchQueue

Example:

// Delay 2 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
     // your code
}

Note: Your application must be active. Also you may have a look at Background modes tutorial

Tomasz Czyżak
  • 1,118
  • 12
  • 13
  • This answer isn't useful because it doesn't address having the app run at a specific time, say 2pm. Dispatch queue simply adds a delay. Starting it at the required time necessitates additional functionality that @Nicolas Buquet provided, where you calculate the difference between the current time and the desired start time. – ch1maera Feb 06 '18 at 00:20