Object X van klasse Y implementeert methodSignatureForSelector niet in Swift

Ik heb een klas Persoon die meerdere keren wordt geïnstantieerd. Elke persoon krijgt zijn eigen timer. Bij in mijn initvoor Personroep ik startTimer()aan.

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)")
 }
...
...
}

Dus ik heb mogelijk 3 instanties van Persoon in een array van Person[]. Ik krijg een foutmelding:

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

Ik heb ergens anders gelezen dat ik zou erven van NSObjectmaar dit is in Swift en niet in Obj-C. De functie bevindt zich binnen de klas, dus ik weet niet zeker wat ik moet doen.


Antwoord 1, autoriteit 100%

Beschouw NSObjectniet als een Objective-C-klasse, beschouw het als een Cocoa/Foundation-klasse. Ook al gebruik je Swift in plaats van Objective-C, je gebruikt nog steeds dezelfde frameworks.

Twee opties: (1) voeg het kenmerk dynamictoe aan de functie waarnaar u wilt verwijzen als selector:

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

Of (2) declareer Personals een subklasse van NSObject, en roep dan gewoon super.init()aan het begin van uw initialisatie :

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()
    }
}

Antwoord 2, autoriteit 20%

Sinds XCode6 beta 6 kunt u ‘dynamische’ functie gebruiken

dynamic func timerTick() { .... }

Antwoord 3, autoriteit 5%

Ik had een soortgelijke fout toen ik probeerde te gebruiken
let encodedArchive = NSKeyedArchiver.archivedDataWithRootObject(archive) as NSDatawaarbij archive een array was van een aangepaste klasse. Ik ontdekte dat het verklaren van die aangepaste klasse als een subklasse van NSObject en NSCoding de truc deed. Er zijn nog een paar regels nodig om te voldoen aan het protocol van NSCoding, dus het ziet er ongeveer zo uit om mee te beginnen:

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

Other episodes