Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 632
spacecash21 Avatar asked Apr 10 '15 12:04

spacecash21


2 Answers

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)
like image 65
Paulw11 Avatar answered Sep 28 '22 04:09

Paulw11


Also helps to make sure the target object (self in your case) is a subclass of NSObject

var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: <THIS MUST BE NSOBJECT SUBCLASS>, selector: "runRockRotation:", userInfo: rock, repeats: false)
like image 29
Noam Avatar answered Sep 28 '22 06:09

Noam