Search code examples
iosswiftselectornstimer

Swift selector - unrecognized selector sent to instance


I have a function:

func runRockRotation(rockSprite: SKSpriteNode){
    startRockRotationAnimation(rockSprite, isRock: true)
}

When I call it like this:

runRockRotation(rock)

it works, but I can't seem to be able to put it inside a NSTimer selector.

var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "runRockRotation:", userInfo: rock, repeats: false)

Read a lot of forums, tried this:

var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "runRockRotation()", userInfo: rock, repeats: false)
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "runRockRotation(_)", userInfo: rock, repeats: false)
var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "runRockRotation", userInfo: rock, repeats: false)

Also, tried without rock, using nil, but nothing seems to work.

Every time I get:

2015-04-10 15:49:03.830 Meh[1640:218030] -[__NSCFTimer runAction:completion:]: unrecognized selector sent to instance 0x174166840
2015-04-10 15:49:03.832 Meh[1640:218030] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFTimer runAction:completion:]: unrecognized selector sent to instance 0x174166840'

How do I call my function in a selector with a parameter? I know how to do that in Objective C, but can't seem to do it in Swift. All help will be appreciated.


Solution

  • Check the documentation for scheduledTimerWithTimeInterval

    You will see that

    The selector should have the following signature: timerFireMethod: (including a colon to indicate that the method takes an argument).

    The timer passes itself as the argument, thus the method would adopt the following pattern: - (void)timerFireMethod:(NSTimer *)timer

    Your function doesn't match this pattern, so the appropriate selector cannot be found.

    Use something like -

    func runRockRotationForTimer(_ timer: NSTimer){
        self.runRockRotation(timer.userInfo as? SKSpriteNode)
        timer.invalidate();
    }
    

    and schedule it using

    var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "runRockRotationForTimer:", userInfo: rock, repeats: false)