@objc 对 Swift 3 的要求?

@objc requirement for Swift 3?

知道为什么我的 Swift 3 iOS 应用程序,这个

@objc(mapView:rendererForOverlay:) func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {

触发器, 但是如果我用这个

替换上面的语句
func mapView(mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {

不触发。

一个明显的问题是,在 Swift 3 中,这不是正确的签名:

func mapView(mapView: MKMapView, 
    rendererFor overlay: MKOverlay) -> MKOverlayRenderer {

correct signature是:

func mapView(_ mapView: MKMapView, 
    rendererFor overlay: MKOverlay) -> MKOverlayRenderer {

注意区别("underscore")。

如果您的代码不在 class 或 显式 声明符合 MKMapViewDelegate 的扩展声明中,则会发生另一个可能的问题。 Swift 3对这个很挑剔。 (您没有显示足够的上下文让我知道您是否正确理解了那部分。)

@objc 声明通过明确地将此函数桥接到 Objective-C 来解决这两个问题。但是如果你在这两个方面都做得对,Swift 会为你做好桥接工作,@objc 就不需要了。

连马特的回答都是正确的我想解释下划线的原因。

为什么需要下划线?

简答:因为这是方法的声明:

 optional func mapView(_ mapView: MKMapView, 
      rendererFor overlay: MKOverlay) -> MKOverlayRenderer

https://developer.apple.com/reference/mapkit/mkmapviewdelegate/1452203-mapview

长答案:

tl;dr:您需要它来删除 Swift 3.0 中第一个参数的前导参数名称。

要了解你必须了解整个故事:

Objective-C 类似于命名参数:整个方法声明,包括参数声明之前的部分,都是方法标识符的一部分。有了方法……:

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView 
        rendererForOverlay:(id<MKOverlay>)overlay;

…这意味着,方法(选择器)的标识符是mapView:renderForOverlay:。这个系统很简单,而且使用了很长时间。它很强大,因为它使方法重载成为不必要的。

根据Swift的设计原则,为了把工作和简单的事情变得复杂到无法说,不管他们是否工作,他们做了一些技巧:

Swift 具有从 Objective-C 选择器到 Swift 函数和参数标识符的类似转换机制。他们在 Swift 1.2(?) 中找到了一个很好的解决方案,这让事情变得更容易了。后来他们意识到,这个伟大而简单的解决方案令人困惑,他们在 Swift 2.0 中提供了一个新的解决方案,该解决方案迄今为止更强大、更简单。后来他们意识到,更大更简单的解决方案令人困惑,他们在 Swift 3.0 中提供了一个新的解决方案,这是迄今为止更大的解决方案。

虽然在 Swift < 3.0 中,第一个(外部)参数名称默认为空(因为选择器的第一部分成为函数名称)此规则不再适用,您必须指定它。下划线只是表示没有外部名称。因此,您的方法名称已正确翻译为 Objective-C 的选择器。

取函数名mapView,因为_所以没有加外部名字,所以是mapView:。然后它添加下一个外部参数名称renderFor,这导致mapView:renderFor,然后参数名称overlay,将其大写为Overlay,这导致mapView:renderForOverlay: – 正确的选择器。

很容易,很简单。使 Swift 中的事情变得简单易行的另一项功能。在 Objective-C

中更容易