0

So I am using an Objective-C library that makes use of MKMapView. So there is a class:

 @interface BSWeatherMapView : MKMapView
    /** The receiver’s delegate. */
    @property (nonatomic, weak) id<BSWeatherMapViewDelegate> delegate; 

Its protocol is defined with this method:

    @protocol BSWeatherMapViewDelegate<MKMapViewDelegate>
    @optional 
    - (MKAnnotationView *)mapView:(BSWeatherMapView *)mapView viewForAnnotation:(id<MKAnnotation >)annotation;

My swift class has an extension doing the following:

extension ViewController : BSWeatherMapViewDelegate {
func mapView(mapView: BSWeatherMapView!, viewForAnnotation annotation: AnyObject) -> MKAnnotationView! {}
}

When I do this I get the following error: Objective-C method mapView:viewForAnnotation: provided by method mapView(_:viewForAnnotation:) conflicts with optional requirement method mapView(_:viewForAnnotation:) in protocol MKMapViewDelegate

I have no clue how to get past this... anyone?

Thanks,

Ravi Dhorajiya
  • 1,531
  • 3
  • 21
  • 26
  • Unfortunately this is legal in Objective C. Is there a way around this? Our original app was in Objective-C and this all worked fine. – Gamemaker945 Jun 11 '16 at 03:18
  • So is there a way for me to tell it this is the one I am trying to handle and the other once can be ignored? – Gamemaker945 Jun 11 '16 at 05:09

2 Answers2

2

The problem is that this Objective-C declaration is illegal:

@protocol BSWeatherMapViewDelegate<MKMapViewDelegate>
@optional 
- (MKAnnotationView *)mapView:(BSWeatherMapView *)mapView viewForAnnotation:(id<MKAnnotation >)annotation;
@end

The illegality is that MKMapViewDelegate already declares a method called mapView:viewForAnnotation:, but with a different first parameter type. There is no overloading in Objective-C, so it is impossible to distinguish between the MKMapViewDelegate mapView:viewForAnnotation: and the BSWeatherMapViewDelegate mapView:viewForAnnotation:. If the same app were to try to implement both, the runtime would have no way of knowing which is which.

The Objective-C compiler doesn't actually stop you as long as you don't try to implement both methods; it warns but it does not error. (You, while writing your app in Objective-C, have presumably been blithely ignoring the warning; but that was a mistake, as it would have clued you in to the fact that you were already in trouble.) If you had tried to implement both, you would have gotten a "duplicate declaration" compile error.

But the Swift compiler, which can tell the difference between them because it does permit overloading, is more proactive and stops you from implementing either of them. Thus, you can never implement either of them on the Swift side.

Your choices, therefore, are:

  • Abandon use of this library, as it is faulty.

  • Fix the library to be legal (assuming you have access to the source). For example, change the name of the BSWeatherMapViewDelegate method wherever it occurs.

  • Implement these delegate methods only in Objective-C, not in Swift.

matt
  • 515,959
  • 87
  • 875
  • 1,141
1

Unfortunately I could not alter the library nor could I move to a differnent one for the time being. What I ended up doing was I created an Objective-C class that was the delegate for BSWeatherMapViewDelegate. I then created similar methods that each of the delegate methods called. Finally, in swift, I subclassed this intermediate Obj-C class and overrode the intermediate methods. Not an ideal solution but it got the job done. Thank you for all of your suggestions.