Ios 强制模板成为协议
如何确保给定的模板参数是协议 一个Ios 强制模板成为协议,ios,swift,generics,protocols,Ios,Swift,Generics,Protocols,如何确保给定的模板参数是协议 一个gk实体有一个名为component(of type:class)的函数,我想添加组件(of Protocol:Protocol)。它确实是这样的: extension GKEntity { func component<T: Protocol>(ofProtocol: T) -> T? { return self.components.first() { component in return
gk实体
有一个名为component(of type:class)
的函数,我想添加组件(of Protocol: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'
更新: 我的想法是我有一个精灵组件:
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)
}
}
我希望能够随时交换SpriteComponentProtocol。您的代码的问题是
协议
是一种描述Obj-C协议的不透明类型,因此如果您想将SpriteComponentProtocol.self
桥接到它,您需要将SpriteComponentProtocol
标记为@objc
(但即使您这样做了,您也无法强制转换到t
,因为返回的实例不是协议类型的)
但是也就是说,您不需要在这里使用Obj-C协议类型或符合(to:)
方法,您只需在组件(ofType:)
的重载中使用条件类型转换操作符as?
,而不需要GKComponent
对t
的约束:
extension GKEntity {
func component<T>(ofType type: T.Type) -> T? {
return self.components.lazy.flatMap{ $0 as? T }.first
}
}
在Swift 4中,您可以完全删除此重载,而只需使用类存在元类型调用GKEntity
的方法:
let comp = self.entity?.component(ofType: (GKComponent & SpriteComponentProtocol).self)
现在,T
满足了:GKComponent
约束。然后,您可以访问GKComponent
方法和SpriteComponentProtocol
对未包装实例的协议要求。因此,我们可以这样做:self.entity?.component(protocol:SpriteComponentProtocol.self)as?SpriteComponentProtocol
如果我返回一个GKComponentProtocol
而不是模板T,并将objc引用添加到协议中,这需要objc导出,对吗?我的想法是,我对固定类没有要求。相反,我希望它是一个协议,这样我就可以轻松地将其交换到其他内容。非常感谢。我认为这是一个很好的方法,可以确保我以后不会把它搞砸,即使我已经对此进行了测试。我们是否可以将桥默认为{%0}
closure?这是有道理的。不幸的是,我不太了解swift的一般特性。我认为为此编写测试,并使用不同的方法签名,然后是组件(ofType…)
应该可以确保没有人尝试添加与其他组件不一致的新组件。太棒了。如果我在没有@objc的情况下传入协议,编译器不会抱怨。你确定我现在必须这样做吗?@BennX正确,不再需要@objc
)
let comp = self.entity?.component(ofType: (GKComponent & SpriteComponentProtocol).self)