协议只能用作通用约束

时间:2016-10-30 23:44:32

标签: swift generics protocols mkannotation

我有一个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

1 个答案:

答案 0 :(得分:5)

更新

抱歉,我犯了错误。但是没有办法使用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的类型未提供,

您只需删除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)
}