【问题标题】:Non-'@objc' method does not satisfy optional requirement of '@objc' protocol with conditional extension非'@objc' 方法不满足带有条件扩展的'@objc' 协议的可选要求
【发布时间】:2016-12-31 06:39:21
【问题描述】:

我正在尝试使用条件扩展来创建 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,也不会调用委托方法。

我是否误解了“在哪里”在扩展程序中的工作原理?

【问题讨论】:

标签: swift swift-extensions


【解决方案1】:

由于Doug Gregor's proposal: SE-0160.的接受,NSObject 将不再推断 @objc 从 Swift 4 开始

我承认我没有花时间去理解你的错误背后的原因。我只是发布了这个答案,希望其他阅读您问题的人会看到以下建议。

为整个模块的协议提供默认实现是不好的做法,或者说“代码异味”。我会推荐一种替代方法,您可以创建一个自定义类型,例如 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)
    }
}

【讨论】:

  • 虽然这是一个功能性解决方案,但它实际上并没有回答问题。问题是为什么符合 NSObject 并没有消除警告。
猜你喜欢
  • 2017-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多