【问题标题】:Object X of class Y does not implement methodSignatureForSelector in Swift类 Y 的对象 X 没有在 Swift 中实现 methodSignatureForSelector
【发布时间】:2014-06-25 18:11:26
【问题描述】:

我有一个类 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)")
 }
...
...
}

所以我可能在Person[] 的数组中有 3 个 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 中。该功能在课堂上,所以我不知道该怎么做。

【问题讨论】:

  • 您已经发现该类应该继承自 NSObject:class Person : NSObject { ... }。您在寻找不同的解决方案吗?

标签: swift


【解决方案1】:

不要把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()这样装饰函数声明。 NSTimer API 似乎非常依赖于 Obj-C 运行时。
  • 好电话 - 添加到答案中
  • 感谢这解决了我的问题。但是你能解释一下为什么吗? @objc 部分需要什么?
  • NSTimer 使用消息转发来调用目标选择器,这是默认情况下未在 Swift 类型上处理的 Objective-C 功能。当您使用 @objc 属性或从 Objective-C 类继承时,您可以选择使用多个功能,包括消息转发。
  • 不再需要这些解决方案。声明选择器函数dynamic 就足够了。它们都很好,它们仍然可以工作,但是在这个函数上使用dynamic 可能会被视为一种更轻量级的方法。
【解决方案2】:

从 XCode6 beta 6 开始,您可以使用 'dynamic' func

dynamic func timerTick() { .... }

【讨论】:

  • 这解决了我尝试使用 UILocalizedIndexedCollat​​ion.currentCollat​​ion() 的问题
  • 这是一个比让整个类继承自 NSObject 更好的方法。
【解决方案3】:

我在尝试使用时遇到了类似的错误 let encodedArchive = NSKeyedArchiver.archivedDataWithRootObject(archive) as NSData 其中存档是自定义类的数组。我发现将自定义类声明为 NSObject 和 NSCoding 的子类就可以了。它需要多几行才能符合 NSCoding 的协议,所以它看起来像这样开始:

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

  func encodeWithCoder(_aCoder: NSCoder) {   }
}

【讨论】:

    猜你喜欢
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    相关资源
    最近更新 更多