如何确保给定模板参数是协议?
GKEntity
有一个名为component(ofType: class)
的函数,我想添加component(ofProtocol: Protocol)
。它看起来像这样:
extension GKEntity {
func component<T: Protocol>(ofProtocol: T) -> T? {
return self.components.first() { component in
return component.conforms(to: ofProtocol)
} as? T
}
}
我想在一个包含对实体的引用的组件中使用它,如下所示:
let component = self.entity?.component(ofProtocol: SpriteComponentProtocol)
但不知怎的,我总是得到:
显示所有消息
Cannot convert value of type 'SpriteComponentProtocol.Protocol' to expected argument type 'Protocol'
更新
我的想法是我有一个Sprite组件:
protocol SpriteComponentProtocol {
var spriteNode: SKSpriteNode { get set }
}
class SpriteComponent: GKComponent {
var spriteNode: SKSpriteNode?
}
控件的另一个组件:
protocol PlayerControlComponentProtocol {
var steerAngle: Double { get set }
}
class PlayerControlComponent: GKComponent, PlayerControlComponentProtocol {
var steerAngle: Double = 90.0
override func update(deltaTime seconds: TimeInterval) {
//here i do manipulate the spriteComponent.spriteNode
let comp = self.entity?.component(ofProtocol: SpriteComponentProtocol)
}
}
我希望能够随时更换SpriteComponent。
答案 0 :(得分:1)
您的代码存在的问题是Protocol
是一种描述Obj-C协议的opaque类型,因此如果您要将SpriteComponentProtocol.self
桥接到它,则需要标记{{1} } SpriteComponentProtocol
(但即使你这样做了;你也不能转发到@objc
,因为返回的实例不是T
类型的。)< / p>
但话虽如此,您不需要在此处使用Obj-C Protocol
类型或Protocol
方法,您只需使用条件类型转换运算符{{1}在conforms(to:)
的重载中没有 as?
上的component(ofType:)
约束:
GKComponent
我们在这里使用T
是为了避免评估所有extension GKEntity {
func component<T>(ofType type: T.Type) -> T? {
return self.components.lazy.flatMap{ $0 as? T }.first
}
}
,然后评估lazy
和components
以获得第一个元素&# 39; s可转换为flatMap(_:)
(并且在first
为协议类型的情况下,这为我们提供了符合协议的第一个元素。)
然后您可以像这样简单地使用它:
T
在Swift 4中,您可以完全删除此重载,而只需使用类存活元数据类型调用T
&n; component(ofType:)
方法:
protocol SpriteComponentProtocol {
var spriteNode: SKSpriteNode { get set }
}
class PlayerControlComponent: GKComponent {
override func update(deltaTime seconds: TimeInterval) {
let comp = self.entity?.component(ofType: SpriteComponentProtocol.self)
}
}
现在GKEntity
满足let comp = self.entity?.component(ofType: (GKComponent & SpriteComponentProtocol).self)
约束。然后,您可以在未打包的实例上访问T
方法和: GKComponent
协议要求。