如何在Swift中使用类型擦除静态访问泛型子类型?

时间:2017-05-13 13:10:54

标签: swift generics

给定具有关联类型CALayer ..

的协议
protocol LayerQuery {
    associatedtype U:CALayer
    var id:String { get }
    var parent:CALayer { get }
    func fetch() -> U?
    ..
}
extension LayerQuery {
    func fetch() -> U? {
        return ..
    }
    ..
}

..和指定相关类型的子类型的具体类型,例如CAShapeLayer ..

struct CustomBorderQuery : LayerQuery {
    typealias U = CAShapeLayer
    let id:String
    let parent:CALayer
}

..带有某种类型的擦除(必要的邪恶)..

struct AnyLayerQuery : LayerQuery {
    typealias U = CALayer
    var parent: CALayer
    var id: String
    init<Q:LayerQuery>(_ query:Q) where Q.U:CALayer {
        self.parent = query.parent
        self.id = query.id
    }
}

..和用于生成正确查询的工厂。

enum Query {
    case customBorder
    case ..
    func on(_ parent:CALayer) -> AnyLayerQuery  {
        switch self {
        case .customBorder:
            return AnyLayerQuery(CustomBorderQuery(id:"..", parent:parent))
        }
    }
}

如何让此返回该查询的特定子类型:CAShapeLayer 而不只是CALayer

示例呼叫站点:

if let layer = Query.customBorder.on(parentLayer).fetch() {
    // Access property "path" on CAShapeLayer:
    layer.path = UIBezierPath(..).cgPath
}

理想情况下,我不应该贬低(as?)。 Xcode中的代码完成应该提供CAShapeLayer

的接口

1 个答案:

答案 0 :(得分:1)

你的类型擦除掩盖了正在构建的特定类型的东西。这就是重点。您将不得不在某个时候使用向下转换来恢复查询的原始子类型。