非"@objc"方法不满足具有条件扩展的"@objc"协议的可选要求



我试图通过使用条件扩展创建MKMapViewDelegate的默认实现,如下所示:

extension MKMapViewDelegate where Self: NSObject {
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            ...
        }
        func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
            ...
        }
    }

然而,当我编译代码时,我得到警告

非'@objc'方法'mapView(_:viewFor:)'不满足'@objc'协议'MKMapViewDelegate'的可选要求

我期望'Self'与NSObject的一致性将意味着不会发生警告。在警告的顶部,委托方法不会被调用,即使委托实例是一个UIViewController,因此符合NSObject。

我是否误解了'where'在扩展中的工作方式?

由于接受Doug Gregor的建议,NSObject将不再将@objc推断为Swift 4的SE-0160 .

我承认我没有花时间去理解你错误背后的原因。我只是把这个答案贴出来,希望其他人看到你的问题会看到下面的建议。

为整个模块提供协议的默认实现是不好的做法,或"代码气味"。我建议采用另一种方法,即创建一个自定义类型,例如MapViewDelegate,它具有一些默认行为,可以在显式符合protocol的类型之间共享。

例如:

import MapKit
protocol MapViewDelegate: MKMapViewDelegate {}
extension MapViewDelegate where Self: NSObject {
    func annotationView(for annotation: MKAnnotation, in mapView: MKMapView) -> MKAnnotationView? {
        …
    }
    func renderer(for overlay: MKOverlay, in mapView: MKMapView) -> MKOverlayRenderer {
        …
    }
}
final class MyMapDelegate: NSObject, MapViewDelegate {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        return annotationView(for: annotation, in: mapView)
    }
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        return renderer(for: overlay, in: mapView)
    }
}

最新更新