Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scheduling a Closure Expression in Swift

I'd like to be able to schedule a closure to be run at either an absolute or relative time in the future. I see that I can use NSTimer to schedule a selector to be called later, but this is not what I want. I would prefer to see something like this:

let timer = NSTimer.scheduleWithTimeInterval(
    ti: NSTimerInterval(1.0),
    action: {
        // do something
    }
)

Is there a built-in way to do something like this in Swift?

edit

I've now come across dispatch_after which seems to be more in line with what I want, but I'm open to other ideas.

like image 668
cwharris Avatar asked Jun 18 '14 19:06

cwharris


2 Answers

dispatch_after should be a fine solution since there are no block based NSTimer methods.

Alternatively you could use (or create) a simple block based NSTimer category (or an extension in Swift): https://github.com/jivadevoe/NSTimer-Blocks

like image 73
bjtitus Avatar answered Sep 27 '22 19:09

bjtitus


I was looking for the same thing. I found this Github Gist by Nate Cook, which is an NSTimer extension that allows you to pass in a closure. The following code is copied from that Gist with the comments removed. See the link above for the full and/or updated version.

extension NSTimer {

    class func schedule(delay delay: NSTimeInterval, handler: NSTimer! -> Void) -> NSTimer {
        let fireDate = delay + CFAbsoluteTimeGetCurrent()
        let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, 0, 0, 0, handler)
        CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes)
        return timer
    }

    class func schedule(repeatInterval interval: NSTimeInterval, handler: NSTimer! -> Void) -> NSTimer {
        let fireDate = interval + CFAbsoluteTimeGetCurrent()
        let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, interval, 0, 0, handler)
        CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes)
        return timer
    }
}

The first function allows you to schedule a delayed event. The second allows you to schedule a repeated event.

Usage:

var count = 0
NSTimer.schedule(repeatInterval: 1) { timer in
    count += 1
    print(count)
    if count >= 10 {
        timer.invalidate()
    }
}

NSTimer.schedule(delay: 5) { timer in
    print("5 seconds")
}

(I modified the print(++count) line in the original since ++ is deprecated now.)

like image 29
Suragch Avatar answered Sep 27 '22 21:09

Suragch