4

I have a MapViewController for presenting annotations on map. It contains an object of type MapPresentable.

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

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

MapViewController can also present route on map in case mapPresentable conforms to RoutePresentable protocol.

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

But when checking made inside MapViewController

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

I got this Error:

Protocol 'RoutePresentable' can only be used as a generic constraint because it has Self or associated type requirements
GeRyCh
  • 1,580
  • 3
  • 13
  • 23

1 Answers1

5

Updated

Sorry, I make mistakes. But there is no way to cast a protocol with associated type.

Hope this will help.

As i known the routePresentable.getRouteLocations has nothing to do with protocol MapPresentable.

So you can divide RoutePresentable to two protocol:

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)
}

Original

Because routePresentable.annotations's Type is unprovided,

You can just remove associatedtype AnnotationElement: MKAnnotation.

Or user generic struct instead:

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)
}
beeth0ven
  • 1,857
  • 15
  • 18
  • Thank you for your answer! Unfortunately, I didn't understand you generic solution. MapPresentable & RoutePresentable must be protocols (there are actual types conforming to it). And how exactly cast statement will work? In this case MapPresentable & RoutePresentable are different structs.. – GeRyCh Oct 31 '16 at 10:29
  • Great! Your update helped solve the casting issue! Thank you! – GeRyCh Nov 01 '16 at 09:33