2015-12-22 1 views
9

Wie listet man alle Klassen auf, die ein bestimmtes Protokoll in Swift implementieren?Wie listet man alle Swift-konformen Klassen auf?

Sagen wir ein Beispiel haben:

protocol Animal { 
    func speak() 
} 

class Cat:Animal { 
    func speak() { 
     print("meow") 
    } 
} 

class Dog: Animal { 
    func speak() { 
     print("Av Av!") 
    } 
} 

class Horse: Animal { 
    func speak() { 
     print("Hurrrr") 
    } 
} 

Hier ist meine aktuelle (nicht übersetzbar) Ansatz:

func getClassesImplementingProtocol(p: Protocol) -> [AnyClass] { 
    let classes = objc_getClassList() 
    var ret = [AnyClass]() 

    for cls in classes { 
     if class_conformsToProtocol(cls, p) { 
      ret.append(cls) 
     } 
    } 
    return ret 
} 

func objc_getClassList() -> [AnyClass] { 
    let expectedClassCount = objc_getClassList(nil, 0) 
    let allClasses = UnsafeMutablePointer<AnyClass?>.alloc(Int(expectedClassCount)) 
    let autoreleasingAllClasses = AutoreleasingUnsafeMutablePointer<AnyClass?>(allClasses) 
    let actualClassCount:Int32 = objc_getClassList(autoreleasingAllClasses, expectedClassCount) 

    var classes = [AnyClass]() 
    for i in 0 ..< actualClassCount { 
     if let currentClass: AnyClass = allClasses[Int(i)] { 
      classes.append(currentClass) 
     } 
    } 

    allClasses.dealloc(Int(expectedClassCount)) 

    return classes 
} 

Aber wenn entweder

getClassesImplementingProtocol(Animal.Protocol) oder

getClassesImplementingProtocol(Animal) Aufruf oder

getClassesImplementingProtocol(Animal.self)

Ergebnisse in Xcode Fehler: kann nicht Wert vom Typ (Animal.Protocol) .Type zu erwarteten Argumenttyp 'Protokoll' konvertieren.

Hat jemand geschafft bekommen das funktioniert?

+0

In welcher Zeile tritt der Fehler auf? – luk2302

+0

Ich denke, das könnte für Sie hilfreich sein: http://stackoverflow.com/questions/28124684/swift-check-if-generic-type-conforms-to-protocol –

Antwort

4

Da Sie die Objective-C-Laufzeit verwenden Sie die Art Selbstbeobachtung Sie @objc, um Ihren Code auf diese Weise hinzufügen müssen, um zu bekommen:

@objc protocol Animal { 
    func speak() 
} 

class Cat:Animal { 
    @objc func speak() { 
    print("meow") 
    } 
} 

class Dog: Animal { 
    @objc func speak() { 
    print("Av Av!") 
    } 
} 

class Horse: Animal { 
    @objc func speak() { 
    print("Hurrrr") 
    } 
} 

Beachten Sie, dass diese Art von Art Selbstbeobachtung kann sehr langsam sein.

+0

Dank Bruno, es funktioniert. Was die Performance betrifft, habe ich es einfach gemessen: Auf iPad3 (das ich als langsames Gerät ansehe) dauert es ca. 115ms für ein 'getClassesImplementingProtocol' Call, während es auf iPhone6S 12ms dauert. Für mich wird dies beim Start der App ausgeführt, daher ist die Leistung kein kritischer Punkt. – mixtly87

+0

Nicht so langsam wie ich es erwartet habe, also ist das eine gute Sache! Ich bin froh, dass es für dich geklappt hat. – ColGraff

+1

Gibt es eine Möglichkeit, etwas Ähnliches mit Strukturen zu bekommen? –