2015-12-22 18 views
9

Jak wyświetlić listę wszystkich klas implementujących dany protokół w Swift?Jak wyświetlić listę wszystkich klas zgodnych z protokołem w Swift?

że mamy przykład:

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") 
    } 
} 

Oto mój aktualny (nie compilable) podejście:

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 
} 

Ale kiedy dzwoni albo

getClassesImplementingProtocol(Animal.Protocol) lub

getClassesImplementingProtocol(Animal) lub

getClassesImplementingProtocol(Animal.self)

skutkuje błędem Xcode: nie można przekonwertować wartości typu (Animal.Protocol) .typ do oczekiwanego typu argumentu „Protokół”.

Czy ktoś zarządzał działaniem?

+0

W jakim wierszu występuje błąd? – luk2302

+0

Myślę, że to może być pomocne dla Ciebie: http://stackoverflow.com/questions/28124684/swift-check-if-generic-type-conforms-to-protocol –

Odpowiedz

4

Ponieważ używasz Objective-C Runtime Aby uzyskać typ introspekcji trzeba dodać @objc do kodu w ten sposób:

@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") 
    } 
} 

pamiętać, że ten rodzaj introspekcji typu może być bardzo powolne.

+0

Dzięki Bruno działa. Jeśli chodzi o wydajność, to po prostu to zmierzyłem: na iPadzie3 (który uważam za wolny) zajmuje około 115ms dla wywołania 'getClassesImplementingProtocol', podczas gdy na iPhone6S zajmuje to 12ms. Dla mnie jest to wykonywane jeden raz podczas uruchamiania aplikacji, więc wydajność nie jest krytycznym problemem. – mixtly87

+0

Nie tak wolno, jak się spodziewałem, więc to dobrze! Cieszę się, że to dla ciebie zadziałało. – ColGraff

+1

Czy jest jakiś sposób, aby uzyskać coś podobnego w strukturach? –

Powiązane problemy