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.