类Y的对象X在Swift中未实现methodSignatureForSelector


89

我有一个类Person被多次实例化。每个人都有自己的计时器。当我在initPerson我打电话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中。该函数在该类中,因此我不确定该怎么做。


4
你已经想通了该类应该从NSObject的继承:class Person : NSObject { ... }。您在寻找其他解决方案吗?
马丁R

Answers:


160

不要想 NSObject视为Objective-C类,而应将其视为可可/基础类。即使您使用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()
    }
}

3
您还应该能够像这样装饰函数声明@objc func timerTick()。NSTimer API似乎非常依赖于Obj-C Runtime。
macshome 2014年

好电话-添加到答案中
Nate Cook

1
感谢此修复了我的问题。但是你能解释为什么吗?它需要@objc部分是什么?
侵略者

NSTimer使用消息转发来调用目标选择器,这是默认情况下对Swift类型不处理的Objective-C功能。当您使用@objc属性或从Objective-C类继承时,您选择了几种功能,包括消息转发。
内特·库克

2
这些解决方案都不再需要。声明选择器函数就足够了dynamic。它们都很好,而且都可以使用,但是dynamic在此功能上使用可能会被视为一种更轻量级的方法。
马特2015年

32

从XCode6 beta 6开始,您可以使用“动态”功能

dynamic func timerTick() { .... }

这解决了我尝试使用UILocalizedIndexedCollat​​ion.currentCollat​​ion()的问题
DogCoffee 2015年

与使整个类继承自NSObject相比,这是一种更好的方法。
bobics

8

尝试使用let encodedArchive = NSKeyedArchiver.archivedDataWithRootObject(archive) as NSDataArchive是自定义类的数组时,我遇到了类似的错误 。我发现将自定义类声明为NSObject和NSCoding的子类可以解决问题。它将需要更多的行才能符合NSCoding的协议,因此它看起来像这样:

class Person: NSObject, NSCoding {
  init() {
    super.init()
  }

  func encodeWithCoder(_aCoder: NSCoder) {   }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.