L’object X della class Y non implementa methodSignatureForSelector in Swift

Ho una persona di class che viene istanziata più volte. Ogni persona ottiene il proprio timer. Nel mio init for Person chiamo startTimer() .

 class Person { var timer = NSTimer() func startTimer() { timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("timerTick"), userInfo: nil, repeats: true) } func timerTick() { angerLevel++ println("Angry! \(angerLevel)") } ... ... } 

Quindi potrei avere 3 istanze di Persona in un array di Person[] . Sto ottenendo un errore:

 2014-06-25 13:57:14.956 ThisProgram[3842:148856] *** NSForwarding: warning: object 0x113760048 of class '_TtC11ThisProgram6Person' does not implement methodSignatureForSelector: -- trouble ahead 

Ho letto altrove che dovrei ereditare da NSObject ma questo è in Swift non Obj-C. La funzione è all’interno della class, quindi non sono sicuro di cosa fare.

Non pensare a NSObject come a una class Objective-C, NSObject come una class Cocoa / Foundation. Anche se stai usando Swift invece di Objective-C, stai ancora utilizzando tutti gli stessi framework.

Due opzioni: (1) aggiungi l’attributo dynamic alla funzione che vuoi fare riferimento come selettore:

  dynamic func timerTick() { self.angerLevel++ print("Angry! \(self.angerLevel)") } 

Oppure (2) dichiara Person come sottoclass di NSObject , quindi chiama semplicemente super.init() all’inizio del tuo inizializzatore:

 class Person: NSObject { var timer = NSTimer() var angerLevel = 0 func startTimer() { print("starting timer") timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timerTick", userInfo: nil, repeats: true) } func timerTick() { self.angerLevel++ print("Angry! \(self.angerLevel)") } override init() { super.init() self.startTimer() } } 

Dal momento che XCode6 beta 6, è ansible utilizzare la funzione ‘dynamic’

 dynamic func timerTick() { .... } 

Ho avuto un errore simile cercando di utilizzare let encodedArchive = NSKeyedArchiver.archivedDataWithRootObject(archive) as NSData cui l’archivio era un array di una class personalizzata. Ho scoperto che dichiarare che la class personalizzata come sottoclass di NSObject e NSCoding ha fatto il trucco. Richiederà poche altre linee per conformarsi al protocollo di NSCoding, quindi sarà simile a questo per iniziare:

 class Person: NSObject, NSCoding { init() { super.init() } func encodeWithCoder(_aCoder: NSCoder) { } }