21

I'm trying to pass an argument to a method that is called by NSTimer in my code. It is throwing an exception. This is how I'm doing it. Circle is my custom class.

    var circle = Circle()
    var timer = NSTimer.scheduledTimerWithInterval(1.0, target: self, selector: animate, userInfo: circle, repeats: true)

Below is the method that is being called

    func animate(circle: Circle) -> Void{
      //do stuff with circle
    }

Note: The method is in the same class that it is being called. So I believe i've set the target correctly.

Raghu
  • 361
  • 1
  • 2
  • 11

2 Answers2

41

The selector you use with NSTimer is passed the NSTimer object as it's one and only parameter. Put the circle object in it as userInfo and you can extract it when the timer fires.

var circle = Circle()
var timer = NSTimer.scheduledTimerWithInterval(1.0, target: self, selector: "animate:", userInfo: circle, repeats: true)

func animate(timer:NSTimer){
  var circle = timer.userInfo as Circle
  //do stuff with circle
}
Pung Worathiti Manosroi
  • 1,432
  • 1
  • 20
  • 23
Andy
  • 4,441
  • 1
  • 19
  • 16
  • How about two parameters? – tpbafk Oct 23 '20 at 12:01
  • pass the two parameters as a tuple to userInfo? or make a custom struct that encapsulates the two params? I'm not able to try this right now, bt maybe that gives you a hint. ask again if you are still stuck – Andy Oct 25 '20 at 16:22
0

Your selector needs to be a string unless that's supposed to be an ivar. Also, your animate function has the wrong signature. The following changes should get you moving again:

var circle = Circle()
var timer = NSTimer.scheduledTimerWithInterval(1.0, target: self, selector: "animate", userInfo: circle, repeats: true)

func animate(circle: Circle) -> () {
  //do stuff with circle
}

The function really doesn't need to return the empty tuple; it can be written without the -> ()

I've also seen the selector string wrapped in a "Selector()" method: Selector("animate"). It works either way.

I've been messing with NSTimer and closures myself and wrote an article on it: Using Swift's Closures With NSTimer

samullen
  • 2,380
  • 2
  • 17
  • 18
  • String replacement in Xcode : @"bla bla"; String replacement in Swift : "bla bla" So this is correct answer. – Kemal Can Kaynak Jul 22 '14 at 14:31
  • Still does not seem to work. I get the following error message *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: unrecognized selector sent to instance 0x10da13d60' – Raghu Jul 22 '14 at 16:39
  • The circle argument can't be passed, but it looks like it's already a property. try: func animate() { //do stuff with self.circle } – samullen Jul 22 '14 at 18:34
  • Well that's the problem. I have a lot of circle objects that need to be animated periodically. So they need to be passed into that method – Raghu Jul 22 '14 at 19:08
  • 1
    `selector: "animate"` should be `selector: "animate:"`. – NobodyNada Mar 16 '15 at 00:04