【问题标题】:Protocol can only be used as a generic constraint协议只能用作通用约束
【发布时间】:2016-10-30 23:44:32
【问题描述】:

我有一个 MapViewController 用于在地图上显示注释。它包含一个 MapPresentable 类型的对象。

protocol MapPresentable {
    associatedtype AnnotationElement: MKAnnotation
    var annotations: [AnnotationElement] { get }
}

class MapViewController<M: MapPresentable>: UIViewController {
    var mapPresentable: M!
}

如果mapPresentable 符合 RoutePresentable 协议,MapViewController 也可以在地图上显示路线。

protocol RoutePresentable: MapPresentable {
    var getRouteLocations: [CLLocation] { get }
}

但是在MapViewController内部进行检查时

if let routePresentable = mapPresentable as? RoutePresentable {
    showRoute(routePresentable.getRouteLocations)
}

我收到此错误:

Protocol 'RoutePresentable' can only be used as a generic constraint because it has Self or associated type requirements

【问题讨论】:

    标签: swift generics protocols mkannotation


    【解决方案1】:

    更新

    对不起,我犯了错误。但是没有办法用associated type 强制转换协议。

    希望这会有所帮助。

    据我所知,routePresentable.getRouteLocations 与协议 MapPresentable 无关。

    所以你可以把RoutePresentable分成两个协议:

    protocol MapPresentable {
        associatedtype AnnotationElement: MKAnnotation
        var annotations: [AnnotationElement] { get }
    }
    
    class MapViewController<M: MapPresentable>: UIViewController {
        var mapPresentable: M!
    
    }
    
    protocol RoutePresentable: MapPresentable, CanGetRouteLocations {}
    
    protocol CanGetRouteLocations {
        var getRouteLocations: [CLLocation] { get }
    }
    
    
    if let routePresentable = mapPresentable as? CanGetRouteLocations {
        showRoute(routePresentable.getRouteLocations)
    }
    

    原创

    因为routePresentable.annotations的Type没有提供,

    你可以删除associatedtype AnnotationElement: MKAnnotation

    或者改为用户通用结构:

    struct MapPresentable<AnnotationElement: MKAnnotation> {
        var annotations: [AnnotationElement] = []
    }
    
    struct RoutePresentable<AnnotationElement: MKAnnotation> {
        var mapPresentable: MapPresentable<AnnotationElement>
        var getRouteLocations: [CLLocation] = []
    }
    
    class MapViewController<AnnotationElement: MKAnnotation>: UIViewController {
    
        var mapPresentable: MapPresentable<AnnotationElement>!
    
    }
    
    if let routePresentable = mapPresentable as? RoutePresentable<MKAnnotation> {
        showRoute(routePresentable.getRouteLocations)
    }
    

    【讨论】:

    • 感谢您的回答!不幸的是,我不明白你的通用解决方案。 MapPresentable & RoutePresentable 必须是协议(有符合它的实际类型)。 cast 语句究竟是如何工作的?在这种情况下 MapPresentable 和 RoutePresentable 是不同的结构..
    • 太棒了!您的更新帮助解决了选角问题!谢谢!
    猜你喜欢
    • 2022-08-15
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 2016-02-18
    • 1970-01-01
    相关资源
    最近更新 更多