[英]How to list all classes conforming to protocol in Swift?
如何列出在 Swift 中實現給定協議的所有類?
假設我們有一個例子:
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")
}
}
這是我當前的(不可編譯的)方法:
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
}
但是當調用
getClassesImplementingProtocol(Animal.Protocol)
或
getClassesImplementingProtocol(Animal)
或
getClassesImplementingProtocol(Animal.self)
導致 Xcode 錯誤:無法將類型 (Animal.Protocol).Type 的值轉換為預期的參數類型“Protocol”。
有沒有人設法讓這個工作?
由於您正在使用 Objective-C 運行時來獲取類型自省,因此您需要以這種方式將@objc
添加到您的代碼中:
@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")
}
}
請注意,這種類型自省可能非常慢。
在速度方面,您可以在一個 for 中完成,並避免像這樣遍歷所有類:
func getClassesConformingProtocol(p: Protocol)-> [AnyClass]{
let expectedClassCount = objc_getClassList(nil, 0)
let allClasses = UnsafeMutablePointer<AnyClass>.allocate(capacity: Int(expectedClassCount))
let autoreleasingAllClasses = AutoreleasingUnsafeMutablePointer<AnyClass>(allClasses)
let actualClassCount:Int32 = objc_getClassList(autoreleasingAllClasses, expectedClassCount)
var classes = [AnyClass]()
for i in 0 ..< actualClassCount {
let currentClass = allClasses[Int(i)]
if class_conformsToProtocol(currentClass, p) {
classes.append(currentClass)
}
}
return classes
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.