J'ai une classe Person qui est instanciée plusieurs fois. Chaque personne a sa propre minuterie. Sur mon init
pour Person
j'appelle 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)")
}
...
...
}
Je peux donc avoir 3 instances de Person dans un tableau de Person[]
. J'obtiens une erreur:
2014-06-25 13:57:14.956 ThisProgram[3842:148856] *** NSForwarding: warning: object 0x113760048 of class '_TtC11ThisProgram6Person' does not implement methodSignatureForSelector: -- trouble ahead
J'ai lu ailleurs que je devrais hériter NSObject
mais c'est dans Swift pas Obj-C. La fonction est dans la classe donc je ne sais pas quoi faire.
class Person : NSObject { ... }
. Cherchez-vous une solution différente?Réponses:
Ne pensez pas
NSObject
à une classe Objective-C, pensez-y comme à une classe Cocoa / Foundation. Même si vous utilisez Swift au lieu d'Objective-C, vous utilisez toujours les mêmes frameworks.Deux options: (1) ajoutez l'
dynamic
attribut à la fonction que vous souhaitez référencer en tant que sélecteur:Ou (2) déclarez
Person
comme une sous-classe deNSObject
, puis appelez simplementsuper.init()
au début de votre initialiseur:la source
@objc func timerTick()
. L'API NSTimer semble être assez dépendante du Runtime Obj-C.NSTimer
utilise le transfert de message pour appeler le sélecteur ciblé, qui est une fonctionnalité Objective-C non gérée par défaut sur les types Swift. Lorsque vous utilisez l'@objc
attribut ou héritez d'une classe Objective-C, vous optez pour plusieurs fonctionnalités, notamment le transfert de message.dynamic
. Ils sont tous les deux bons et fonctionnent toujours tous les deux, mais l'utilisationdynamic
de cette fonction peut être considérée comme une approche plus légère.Depuis XCode6 beta 6, vous pouvez utiliser la fonction 'dynamique'
la source
J'ai eu une erreur similaire en essayant d'utiliser
let encodedArchive = NSKeyedArchiver.archivedDataWithRootObject(archive) as NSData
où archive était un tableau d'une classe personnalisée. J'ai trouvé que déclarer cette classe personnalisée en tant que sous-classe de NSObject et NSCoding a fait l'affaire. Il faudra quelques lignes de plus pour se conformer au protocole de NSCoding, donc ça ressemblera à quelque chose comme ça pour commencer:la source