クラスYのオブジェクトXはSwiftのmethodSignatureForSelectorを実装していません


89

私は複数回インスタンス化される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が、これはObj-CではなくSwiftにあります。関数はクラス内にあるため、どうすればよいかわかりません。


4
クラスはNSObject:から継承する必要があることはすでにわかりましたclass Person : NSObject { ... }。別のソリューションをお探しですか?
マーティンR

回答:


160

NSObjectObjective-Cクラスではなく、Cocoa / Foundationクラスと考えてください。Objective-Cの代わりにSwiftを使用している場合でも、同じフレームワークをすべて使用しています。

2つのオプション:(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ランタイムにかなり依存しているようです。
macshome 2014年

良いコール-答えに追加
ネイト・クック

1
このおかげで私の問題を修正しました。しかし、その理由を説明できますか?@objc部分は何が必要ですか?
アグレッサー

NSTimerメッセージ転送を使用してターゲットセレクターを呼び出します。これは、デフォルトではSwiftタイプでは処理されないObjective-Cの機能です。@objc属性を使用するか、Objective-Cクラスから継承すると、メッセージ転送などのいくつかの機能が有効になります。
ネイト・クック

2
これらのソリューションはどちらも必要ありません。セレクター関数を宣言するだけで十分dynamicです。どちらも優れていて、どちらもdynamic機能しますが、この1つの関数を使用すると、より軽量なアプローチが見られる場合があります。
2015年

32

XCode6ベータ6以降、「動的」関数を使用できます

dynamic func timerTick() { .... }

これは、UILocalizedIndexedCollat​​ion.currentCollat​​ion()を使用しようとする私の問題を解決しました
DogCoffee 2015

これは、クラス全体をNSObjectから継承するよりも優れたアプローチです。
bobics

8

let encodedArchive = NSKeyedArchiver.archivedDataWithRootObject(archive) as NSDataアーカイブがカスタムクラスの配列である場合に、同様のエラーが発生しました 。そのカスタムクラスをNSObjectおよびNSCodingのサブクラスとして宣言するとうまくいくことがわかりました。NSCodingのプロトコルに準拠するには、さらに数行が必要になるため、最初は次のようになります。

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

  func encodeWithCoder(_aCoder: NSCoder) {   }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.