Y sınıfının X nesnesi, Swift'de methodSignatureForSelector uygulamıyor


89

Birden çok kez örneklenen bir sınıf Kişi var Her kişi kendi zamanlayıcısına sahip. Benim initiçin Personararım 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)")
 }
...
...
}

Yani bir dizi içinde 3 Kişi örneğim olabilir Person[]. Bir hata alıyorum:

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

Miras almam gereken başka bir yerde okudum NSObjectama bu Obj-C'de değil Swift'de. İşlev sınıf içinde olduğundan ne yapacağımı bilmiyorum.


4
Zaten sınıf NSObject alması gerektiğini anladım: class Person : NSObject { ... }. Farklı bir çözüm mü arıyorsunuz?
— Martin R

Yanıtlar:


160

Düşünmeyin NSObjectbir Objective-C sınıfı olarak, bir Kakao / Vakıf sınıf olarak düşün. Objective-C yerine Swift kullanıyor olsanız bile, hala aynı çerçeveleri kullanıyorsunuz.

İki seçenek: (1) dynamicözniteliği seçici olarak başvurmak istediğiniz işleve ekleyin :

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

Veya (2) Personalt sınıfı olarak beyan edin NSObject, ardından super.init()başlatıcınızın başında çağırın :

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
Ayrıca işlev bildirimini bu şekilde dekore edebilmelisiniz @objc func timerTick(). NSTimer API, Obj-C Runtime'a oldukça bağımlı görünüyor.
— macshome

İyi çağrı - yanıta eklendi
— Nate Cook

1
Teşekkürler bu sorunu DÜZELTİN. Ama nedenini açıklayabilir misin? @Objc kısmına neye ihtiyacı var?
— Saldırgan

NSTimerVarsayılan olarak Swift türlerinde ele alınmayan bir Hedef-C özelliği olan hedef seçiciyi çağırmak için mesaj yönlendirmeyi kullanır. @objcÖzniteliği kullandığınızda veya bir Objective-C sınıfından miras aldığınızda, mesaj iletmeyi de içeren birkaç özelliği seçmiş olursunuz.
— Nate Cook

2
Artık bu çözümlerin hiçbirine ihtiyaç duyulmuyor. Seçici fonksiyonun bildirilmesi yeterlidir dynamic. İkisi de iyi ve ikisi de hala çalışıyor, ancak dynamicbu tek işlevi kullanmak daha hafif bir yaklaşım olarak görülebilir.
— mat

32

XCode6 beta 6'dan beri, 'dinamik' işlevi kullanabilirsiniz.

dynamic func timerTick() { .... }

bu UILocalizedIndexedCollation.currentCollation ()
— DogCoffee

Bu, tüm sınıfın NSObject'ten miras alınmasına kıyasla daha iyi bir yaklaşımdır.
— bobics

8

let encodedArchive = NSKeyedArchiver.archivedDataWithRootObject(archive) as NSDataArşivin özel bir sınıf dizisi olduğu yerde kullanmaya çalışırken benzer bir hatayla karşılaştım . Bu özel sınıfı NSObject ve NSCoding'in bir alt sınıfı olarak bildirmenin hile yaptığını buldum. NSCoding protokolüne uymak için birkaç satır daha gerekecek, bu yüzden başlamak için şuna benzer bir şeye benzeyecek:

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

  func encodeWithCoder(_aCoder: NSCoder) {   }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.