Code Monkey home page Code Monkey logo

swiftytimer's Introduction

SwiftyTimer

Platforms CI Status CocoaPods Carthage compatible Swift version

Modern Swifty API for NSTimer

SwiftyTimer allows you to instantly schedule delays and repeating timers using convenient closure syntax. It's time to get rid of Objective-C cruft.

Read Swifty APIs: NSTimer for more information about this project.

Usage

You can easily schedule repeating and non-repeating timers (repeats and delays) using Timer.every and Timer.after:

Timer.every(0.7.seconds) {
    statusItem.blink()
}

Timer.after(1.minute) {
    println("Are you still here?")
}

You can specify time intervals with these intuitive helpers:

100.ms
1.second
2.5.seconds
5.seconds
10.minutes
1.hour
2.days

You can pass method references instead of closures:

Timer.every(30.seconds, align)

Manual scheduling

If you want to make a timer object without scheduling, use new(after:) and new(every:):

let timer = Timer.new(every: 1.second) {
    println(self.status)
}

(This should be defined as an initializer, but a bug in Foundation prevents this)

Call start() to schedule timers created using new. You can optionally pass the run loop and run loop modes:

timer.start()
timer.start(modes: .defaultRunLoopMode, .eventTrackingRunLoopMode)

Invalidation

If you want to invalidate a repeating timer on some condition, you can take a Timer argument in the closure you pass in:

Timer.every(5.seconds) { (timer: Timer) in
    // do something
    
    if finished {
        timer.invalidate()
    }
}

Installation

Note: If you're running Swift 2, use SwiftyTimer v1.4.1

CocoaPods

If you're using CocoaPods, just add this line to your Podfile:

pod 'SwiftyTimer'

Install by running this command in your terminal:

pod install

Then import the library in all files where you use it:

import SwiftyTimer

Carthage

Just add to your Cartfile:

github "radex/SwiftyTimer"

Manually

Simply copy Sources/SwiftyTimer.swift to your Xcode project.

More like this

If you like SwiftyTimer, check out SwiftyUserDefaults, which applies the same swifty approach to NSUserDefaults.

You might also be interested in my blog posts which explain the design process behind those libraries:

Contributing

If you have comments, complaints or ideas for improvements, feel free to open an issue or a pull request.

Author and license

Radek Pietruszewski

SwiftyTimer is available under the MIT license. See the LICENSE file for more info.

swiftytimer's People

Contributors

adriencanterot avatar asowers1 avatar austinate avatar jayrhynas avatar jmper1 avatar ldiqual avatar ochococo avatar radex avatar regnerjr avatar stephencelis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftytimer's Issues

Usage issue

I was wondering if you can clarify what the difference is between

NSTimer.every(0.7.seconds) {
    println(self.status)
}

and

let timer = NSTimer.new(every: 1.second) {
    println(self.status)
}

Use @objc, not dynamic

Your fire function should be marked as @objc, not as dynamic. This happens to work because dynamic implies @objc, but you don't actually want any of the guarantees of dynamic beyond that of @objc.

Use strong typing instead of ruby-like `1.seconds`

Extending Int and Double with properties second, seconds, minute, etc. seems like a rather bad idea. There's two problems with this:

  1. Anyone using your code in a project with other 3rd-party code that wants to do something similar will have a compile-time naming collision, making it impossible to use either one.
  2. It's weakly-typed. You're still taking NSTimeInterval as your actual time type, and all it takes is for someone to accidentally leave off the .minutes and they'll get the wrong time. This isn't a huge issue, as NSTimeInterval is used everywhere to mean seconds and people are used to it, but we can still do better.

The better approach is to use an actual Duration type that requires the user to type the unit as part of the constructor. With the ruby-like approach you can just say NSTimer.after(1) { ... } but with a proper strong type there's no way to do this. I'd suggest something like

/// A type that represents a given duration.
public struct Duration: Comparable, Hashable, Printable, DebugPrintable {
    /// The time interval of the `Duration`, in seconds.
    let seconds: NSTimeInterval
    /// The time interval of the `Duration`, in minutes.
    var minutes: NSTimeInterval {
        return seconds / 60
    }
    /// The time interval of the `Duration`, in hours.
    var hours: NSTimeInterval {
        return seconds / 3600
    }
    /// The time interval of the `Duration`, in milliseconds.
    /// Sub-millisecond values are truncated.
    var milliseconds: Int64 {
        return Int64(seconds * 1_000)
    }
    /// The time interval of the `Duration`, in microseconds.
    /// Sub-microsecond values are truncated.
    var microseconds: Int64 {
        return Int64(seconds * 1_000_000)
    }
    /// The time interval of the `Duration`, in nanoseconds.
    var nanoseconds: Int64 {
        return Int64(seconds * 1_000_000_000)
    }

    /// Construct a `Duration` for a given number of seconds.
    public init(seconds: NSTimeInterval) {
        self.seconds = seconds
    }
    /// Construct a `Duration` for a given number of minutes.
    public init(minutes: NSTimeInterval) {
        self.init(seconds: minutes * 60)
    }
    /// Construct a `Duration` for a given number of hours.
    public init(hours: NSTimeInterval) {
        self.init(seconds: hours * 3600)
    }
    /// Construct a `Duration` for a given number of milliseconds.
    // Use Int64 because milliseconds are generally not floating-point
    // values
    public init(milliseconds: Int64) {
        self.init(seconds: NSTimeInterval(milliseconds) / 1_000)
    }
    /// Construct a `Duration` for a given number of microseconds.
    public init(microseconds: Int64) {
        self.init(seconds: NSTimeInterval(microseconds) / 1_000_000)
    }
    /// Constructs a `Duration` for a given number of nanoseconds.
    // How much tolerance does a timer actually support?
    public init(nanoseconds: Int64) {
        self.init(seconds: NSTimeInterval(nanoseconds) / 1_000_000_000)
    }

    public var description: String {
        // TODO: Display human-readable string with multiple units
        return toString(seconds)
    }

    public var debugDescription: String {
        return "Duration(\(seconds))"
    }

    public var hashValue: Int {
        return seconds.hashValue
    }
}

public func +(lhs: Duration, rhs: Duration) -> Duration {
    return Duration(seconds: lhs.seconds + rhs.seconds)
}
public func -(lhs: Duration, rhs: Duration) -> Duration {
    return Duration(seconds: lhs.seconds - rhs.seconds)
}
// NB: Don't implement multiplication/division, that doesn't make any sense for
// durations. As such, we don't conform to IntegerArithmeticType either.
public func <(lhs: Duration, rhs: Duration) -> Bool {
    return lhs.seconds < rhs.seconds
}
public func ==(lhs: Duration, rhs: Duration) -> Bool {
    return lhs.seconds == rhs.seconds
}

This way you can then say NSTimer.after(Duration(seconds: 1)) { ... }. You could also experiment with replacing all those initializers with static functions instead (e.g. static func seconds(seconds: NSTimeInterval)) so that way you can say NSTimer.after(.seconds(1)) { ... }.

Can't figure out how to stop timer

Hello!

I want to make a function that starts the timer unless there is a bool true in params (e.g. animateStatusIcon(stop: true)) - in that case I want to stop the timer. Does anyone have an idea what's going on here?

The timer starts but no matter what I do it wont stop.

func animateStatusIcon(stop: Bool? = nil){
        
        let icon = NSImage(named: "statusIcon")
        let iconActive = NSImage(named: "statusIconActive")
        
        let timer = Timer.every(0.4.seconds) {
            self.statusItem.image = icon
            Timer.after(0.2.seconds) {
                self.statusItem.image = iconActive
            }
        }
            
        if(stop == true){
            print(stop!)
            print("should stop now")
            timer.invalidate()
        } else  {
            print(stop)
            print("start")
            timer.start()
        }
        
    }

Support lower deployment targets than 10.11

I haven't perused the source fully, but I would imagine there is no reason that 10.11 is the deployment target for this. I'm wanting to use it in a project that needs to support mavericks.
My guess is it was an oversight, as it was in my project file.

is it supposed to work on a background queue?

Thanks for sharing your work. Trying to do something apparently simple but I see nothing on the console and breakpoints don't stop there. What am I getting wrong?

let backgroundQueue = DispatchQueue(label: "1sec",
    qos: .background,
    target: nil)

backgroundQueue.async {
    Timer.every(1.seconds) {
        self.log.debug("Timer tick at \(Date())")
    }
}

Cheers

Crash when calling fire() after creating timer

The following code worked with 1.3.0 but crashes with 1.4.0:

let timer = NSTimer.every(1) { 
            print("do something!")
        }
timer.fire()

The internal refactoring of not using NSTimer initializers might be the problem.

Timer not working in background

I am trying to use the below in my applicationDidEnterBackground in my AppDelegate.

Timer.after(5.seconds) {
            print ("This is after 5 seconds")
        }

just to test if it works and nothing gets printed out. I want to have a function run after 5 seconds of the app being in the background.

Swift 4.0

To kiedy możemy się spodziewać wersji na 4.0?

Include NSTimer in block?

What are your thoughts about including the timer object in the block?

public class func every(interval: NSTimeInterval, _ block: NSTimer -> Void) -> NSTimer {}

Otherwise I need to declare the variable separately like this:

var timer: NSTimer?
timer = NSTimer.every(5.seconds) {
    timer?.invalidate()
}

Use default arguments naming

When I call a NSTimer.after and pass a function, it doesn't have a argument name for second argument. This feels not natural for me regarding that all other functions usually used default or external names.

  NSTimer.after(1.second, close)

Using default names don't change the nice trailing closure syntax

public class func after(interval: NSTimeInterval, block: () -> Void) -> NSTimer 
...
NSTimer.after(1.second) {
  print("done")
}

If you agree I can make a PR :)

Swift 2.3 compile error

Show in PNG.
Use Xcode 8 and swift 2.3.
I use cocoa pods.
I'm a novice , please tell me detail.
swiftyTimer Version : 1.4.1
Thank you~ 🤗
2bd7ee22-9309-4718-b3e1-9b1ce4c7c7b2

NSTimer.new -> NSTimer.init

Non-scheduling initializers are currently defined as static methods because there was a bug in Foundation causing a crash.

I believe it was fixed, but I don't remember when exactly — it's possible it was only iOS 9/El Capitan, and it still won't work on iOS 8 etc.

If someone could verify this, we could add initializers that are appropriately marked as @available.

PR-s appreciated.

userinfo ?

Is there a way to add userinfo to nstimer ? so i can access a specific timer when making multiple timers dynamically ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.