У меня есть класс Person, который создается несколько раз, и у каждого человека есть свой таймер. После по моему init
для Person
меня позвонить 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)")
}
...
...
}
Так что у меня может быть 3 экземпляра Person в массиве Person[]
. Я получаю сообщение об ошибке:
2014-06-25 13:57:14.956 ThisProgram[3842:148856] *** NSForwarding: warning: object 0x113760048 of class '_TtC11ThisProgram6Person' does not implement methodSignatureForSelector: -- trouble ahead
Я читал в другом месте, что я должен наследовать, NSObject
но это в Swift, а не в Obj-C. Функция находится внутри класса, поэтому я не уверен, что делать.
class Person : NSObject { ... }
. Вы ищете другое решение?Ответы:
Не думайте о
NSObject
классе Objective-C, думайте о нем как о классе Cocoa / Foundation. Несмотря на то, что вы используете Swift вместо Objective-C, вы все равно используете все те же фреймворки.Два варианта: (1) добавить
dynamic
атрибут к функции, на которую вы хотите ссылаться в качестве селектора:dynamic func timerTick() { self.angerLevel++ print("Angry! \(self.angerLevel)") }
Или (2) объявить
Person
как подклассNSObject
, а затем просто вызватьsuper.init()
в начале вашего инициализатора: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() } }
источник
@objc func timerTick()
. API NSTimer, похоже, в значительной степени зависит от среды выполнения Obj-C.NSTimer
использует пересылку сообщений для вызова целевого селектора, который является функцией Objective-C, которая по умолчанию не обрабатывается в типах Swift. Когда вы используете@objc
атрибут или наследуете от класса Objective-C, вы выбираете несколько функций, включая пересылку сообщений.dynamic
. Они оба хороши, и оба по-прежнему работают, но использованиеdynamic
этой функции можно рассматривать как более легкий подход.Начиная с XCode6 beta 6, вы можете использовать динамическую функцию
dynamic func timerTick() { .... }
источник
У меня была аналогичная ошибка при попытке использовать
let encodedArchive = NSKeyedArchiver.archivedDataWithRootObject(archive) as NSData
архив, представляющий собой массив настраиваемого класса. Я обнаружил, что объявление этого настраиваемого класса как подкласса NSObject и NSCoding сделало свое дело. Для соответствия протоколу NSCoding потребуется еще несколько строк, поэтому для начала это будет выглядеть примерно так:class Person: NSObject, NSCoding { init() { super.init() } func encodeWithCoder(_aCoder: NSCoder) { } }
источник