NSTimer.scheduledTimerWithTimeInterval in Swift Pl

2019-01-28 00:30发布

问题:

All the examples I've seen on using the "NSTimer.scheduledTimerWithTimeInterval" within Swift show using the "target: self" parameter, but unfortunately this doesn't work in Swift Playgrounds directly.

Playground execution failed: <EXPR>:42:13: error: use of unresolved
identifier 'self'
  target: self,

Here's an example referenced above that results in the error:

func printFrom1To1000() {
    for counter in 0...1000 {
        var a = counter        
    }
}

var timer = NSTimer.scheduledTimerWithTimeInterval(0,
    target: self,
    selector: Selector("printFrom1To1000"),
    userInfo: nil,
    repeats: false
    )
timer.fire()

回答1:

You really should not be using NSTimer these days. It's consumes a lot of resources, causes unnecessary battery drain, and the API lends itself to ugly code.

Use dispatch_after() instead:

dispatch_after(0, dispatch_get_main_queue()) { () -> Void in
  for counter in 0...1000 {
    var b = counter
  }
}

Of course, since the timer will fire after playground does it's stuff you will need an equivalent of timer.fire() to force the code to execute immediately instead of after a 0 second delay. Here's how that works:

let printFrom1To1000 = { () -> Void in
  for counter in 0...1000 {
    var b = counter
  }
}

dispatch_after(0, dispatch_get_main_queue(), printFrom1To1000)

printFrom1To1000()


回答2:

To get this to run directly within a Swift Playground, you need to embed the printFrom1To1000 function within a class and then set an instance of that class to the "target:" parameter instead of using "self".

Here's a full working example:

class myClass: NSTimer{
    func printFrom1To1000() {
        for counter in 0...1000 {
            var b = counter
        }
    }
}

let myClassInstance = myClass()

var timer = NSTimer.scheduledTimerWithTimeInterval(0,
    target: myClassInstance,
    selector: Selector("printFrom1To1000"),
    userInfo: nil,
    repeats: false
)
timer.fire()


回答3:

If you already have an object you are referencing (i.e., updating a label), you can extend that type and use that function as the Selector. I find this easier than creating a whole new class and instantiating a new object from it.

extension SKLabelNode {
    func updateMe() {
    count++
    label.text = "\(count)"
    }
}

var timer = NSTimer.scheduledTimerWithTimeInterval(0.25,
    target: label,
    selector: Selector("updateMe"),
    userInfo: nil,
    repeats: true)
timer.fire()