在 Swift 中,你能找到一个模块中遵守特定协议的所有类型吗?
In Swift, can you find all types in a module that adhere to a specific protocol?
在Swift4中,是否可以找到当前模块中所有遵循特定协议的类型?
例如,假设我定义了这个协议和这些 类:
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.
不可以在模块中获取 类 的名称。
你可以通过你的代码来计算,使用扩展协议来计算如下代码:)
protocol Animal{}
protocol Vehicle{}
protocol Favorite{
func countImplement()
}
var totalImplement = 0
extension Favorite {
func updateTotalImplement(){
totalImplement += 1
}
}
class Dog : Animal{
}
class Cat : Animal, Favorite{
func countImplement(){
this.updateTotalImplement()
}
}
class Car : Vehicle{
}
class Bicycle : Vehicle, Favorite{
func countImplement(){
this.updateTotalImplement()
}
}
我不相信 Swift 目前有 'native'(不依赖于 Objective-C 运行时)API 进行这种反射。
但是,如果您使用的是 Apple 平台(因此具有 Obj-C 互操作性),您可以获得所有 类 注册的列表Obj-C运行时,然后过滤那些符合给定协议的。这将适用于 Swift 类(甚至那些不继承自 NSObject
的),因为在引擎盖下 Swift 类 是建立在 Obj- 之上的C 类(当有 Obj-C 互操作时)。
因为这只适用于 类(不适用于结构或枚举),您可能希望限制您的协议,以便只有 类 可以符合它:
protocol Favorite : class {}
然后您可以使用 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 { [=11=].compactMap { [=11=] as? Favorite.Type } }
print(classes) // [Bicycle, Cat]
这里我们在 UnsafeBufferPointer
上调用 compactMap(_:)
以取回表示符合 Favorite
的类型的元类型数组(即那些可以转换为存在元类型的元类型Favorite.Type
).
在Swift4中,是否可以找到当前模块中所有遵循特定协议的类型?
例如,假设我定义了这个协议和这些 类:
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.
不可以在模块中获取 类 的名称。
你可以通过你的代码来计算,使用扩展协议来计算如下代码:)
protocol Animal{}
protocol Vehicle{}
protocol Favorite{
func countImplement()
}
var totalImplement = 0
extension Favorite {
func updateTotalImplement(){
totalImplement += 1
}
}
class Dog : Animal{
}
class Cat : Animal, Favorite{
func countImplement(){
this.updateTotalImplement()
}
}
class Car : Vehicle{
}
class Bicycle : Vehicle, Favorite{
func countImplement(){
this.updateTotalImplement()
}
}
我不相信 Swift 目前有 'native'(不依赖于 Objective-C 运行时)API 进行这种反射。
但是,如果您使用的是 Apple 平台(因此具有 Obj-C 互操作性),您可以获得所有 类 注册的列表Obj-C运行时,然后过滤那些符合给定协议的。这将适用于 Swift 类(甚至那些不继承自 NSObject
的),因为在引擎盖下 Swift 类 是建立在 Obj- 之上的C 类(当有 Obj-C 互操作时)。
因为这只适用于 类(不适用于结构或枚举),您可能希望限制您的协议,以便只有 类 可以符合它:
protocol Favorite : class {}
然后您可以使用 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 { [=11=].compactMap { [=11=] as? Favorite.Type } }
print(classes) // [Bicycle, Cat]
这里我们在 UnsafeBufferPointer
上调用 compactMap(_:)
以取回表示符合 Favorite
的类型的元类型数组(即那些可以转换为存在元类型的元类型Favorite.Type
).