163

I don't have a code to sample or anything, because I have no idea how to do it, but can someone please tell me how to delay a function with swift for a set amount of time?

Sulthan
  • 128,090
  • 22
  • 218
  • 270
CoolMAn
  • 1,851
  • 2
  • 12
  • 23

4 Answers4

458

You can use GCD (in the example with a 10 second delay):

Swift 2

let triggerTime = (Int64(NSEC_PER_SEC) * 10)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, triggerTime), dispatch_get_main_queue(), { () -> Void in
    self.functionToCall()
})

Swift 3 and Swift 4

DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: {
    self.functionToCall()
})

Swift 5 or Later

 DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
        //call any function
 }
Mudith Chathuranga Silva
  • 7,253
  • 2
  • 50
  • 58
Farlei Heinen
  • 5,859
  • 1
  • 21
  • 19
  • 3
    GCD stands for "Grand Central Dispatch". Apple define it as: _Grand Central Dispatch (GCD) comprises language features, runtime libraries, and system enhancements that provide systemic, comprehensive improvements to the support for concurrent code execution on multicore hardware in iOS and OS X._ You can find more info [HERE](https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/) – Farlei Heinen Jun 01 '16 at 04:18
  • 1
    What if you wanted to do a fraction of a second say 0.5? – Cody Weaver Aug 17 '16 at 13:38
  • 1
    @CodyWeaver: then you need to change the first line cast to: `let triggerTime = (Int64(Double(NSEC_PER_SEC) * 0.5))` – Farlei Heinen Aug 17 '16 at 21:00
  • What's the reason I should use this method and not something like NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(3), target: self, selector: "functionHere", userInfo: nil, repeats: false) ? – Lucas van Dongen Nov 15 '16 at 22:10
  • I think the main reason is code locality. All the logic is on the same block. But if you want a repeating block NSTimer is better. – Farlei Heinen Nov 15 '16 at 22:21
  • Where do you get DISPATCH_TIME_NOW – Droid Chris Feb 05 '17 at 00:22
  • 1
    @DroidChris - If you are trying this code in Swift 3 you need to use DispatchTime.now() - The code in this answer is for Swift 2 – Farlei Heinen Feb 06 '17 at 20:55
  • how to call the function on class method , where we can use Self.functioncall() ? – Tejas Jun 23 '17 at 14:24
  • This, like 99% of answers to the simple question: "how to delay code?" misses the point. The question does not ask how to call another function after a delay, but to simply add a delay a function. Semantics here are everything. – drew.. Jun 10 '18 at 12:31
  • deadline: .now() + .seconds(10) – nbaroz Jun 28 '20 at 12:27
38

Swift 3 and Above Version(s) for a delay of 10 seconds

    DispatchQueue.main.asyncAfter(deadline: .now() + 10) { [unowned self] in
        self.functionToCall()
    }
Anand
  • 5,323
  • 5
  • 44
  • 58
  • 2
    DispatchQueue.main.asyncAfter(deadline: .now() + 10, execute: { something() }) –  Nov 02 '16 at 14:00
  • 1
    WRT the unowned self, I think it is better to declare unowned self in the lambda, e.g., `{ [unowned self] in self.functionToCall() }`. That way the class doesn't have an unowned reference that it really doesn't need. – sschilli Oct 14 '19 at 16:54
  • @sschilli: Thanks for the comment. Updated the code. – Anand Oct 15 '19 at 05:57
24
 NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(3), target: self, selector: "functionHere", userInfo: nil, repeats: false)

This would call the function functionHere() with a 3 seconds delay

JChomali
  • 255
  • 1
  • 2
  • 6
4

For adding argument to delay function.

First setup a dictionary then add it as the userInfo. Unwrap the info with the timer as the argument.

let arg : Int = 42
let infoDict : [String : AnyObject] = ["argumentInt", arg]

NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(3), target: self, selector: "functionHereWithArgument:", userInfo: infoDict, repeats: false)

Then in the called function

func functionHereWithArgument (timer : NSTimer)
{
    if let userInfo = timer.userInfo as? Dictionary<String, AnyObject>
    {
         let argumentInt : Int = (userInfo[argumentInt] as! Int)
    }
}
KorinW
  • 279
  • 4
  • 10