在 Swift 4 中,是否可以找到当前模块中遵守特定协议的所有类型?
例如,假设我定义了这个协议和这些类:
protocol Animal{}
protocol Vehicle{}
protocol Favorite{}
class Dog : Animal{
}
class Cat : Animal, Favorite{
}
class Car : Vehicle{
}
class Bicycle : Vehicle, Favorite{
}
我想找到所有实现的类型Favorite
。这可以在 C# 中轻松完成,但我不确定在 Swift 中是否可以。
如果有帮助的话,我正在使用 Swift 4。
我不相信 Swift 目前有一个“原生”(不依赖于 Objective-C 运行时)API 来执行这种反射。
但是,如果您使用的是 Apple 平台(因此具有 Obj-C 互操作性),您可以获得所有内容的列表classes向 Obj-C 运行时注册,然后过滤那些符合给定协议的。这适用于 Swift 类(即使是那些不继承自 Swift 类的类)NSObject
)因为在底层,Swift 类是构建在 Obj-C 类之上的(当存在 Obj-C 互操作时)。
因为这仅适用于类(不适用于结构或枚举),所以您可能希望限制您的协议,以便只有类可以符合它:
protocol Favorite : class {}
然后您可以执行以下操作,使用objc_copyClassList https://developer.apple.com/documentation/objectivec/1418762-objc_copyclasslist:
import Foundation
protocol Animal {}
protocol Vehicle {}
protocol Favorite : class {}
class Dog : Animal {}
class Cat : Animal, Favorite {}
class Car : Vehicle {}
class Bicycle : Vehicle, Favorite {}
/// Invokes a given closure with a buffer containing all metaclasses known to the Obj-C
/// runtime. The buffer is only valid for the duration of the closure call.
func withAllClasses<R>(
_ body: (UnsafeBufferPointer<AnyClass>) throws -> R
) rethrows -> R {
var count: UInt32 = 0
let classListPtr = objc_copyClassList(&count)
defer {
free(UnsafeMutableRawPointer(classListPtr))
}
let classListBuffer = UnsafeBufferPointer(
start: classListPtr, count: Int(count)
)
return try body(classListBuffer)
}
// .flatMap in Swift < 4.1
let classes = withAllClasses { $0.compactMap { $0 as? Favorite.Type } }
print(classes) // [Bicycle, Cat]
我们在这里打电话compactMap(_:)
on the UnsafeBufferPointer
返回代表符合以下条件的类型的元类型数组Favorite
(即那些可以转换为存在元类型的Favorite.Type
).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)