@objc对Swift 3的要求?

时间:2016-11-16 15:57:35

标签: objective-c swift swift3 mkmapview

任何想法为什么我的Swift 3 iOS应用程序,这个

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

触发器, 但如果我用上面的语句替换

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

不会触发。

2 个答案:

答案 0 :(得分:2)

即使亚特的答案也是正确的我想解释下划线的原因。

为什么需要下划线?

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

 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类似于从Objective-C选择器到Swift函数和参数标识符的转换机制。他们在Swift 1.2(?)中找到了一个很好的解决方案,这使得事情变得更容易。后来他们认识到,这个伟大而简单的解决方案令人困惑,他们在Swift 2.0中提供了一个新的解决方案,到目前为止它更加容易。后来他们认识到,更大更简单的解决方案令人困惑,他们在Swift 3.0中提供了一种全新的解决方案,远远超过了它。

在Swift&lt; 3.0第一个(外部)参数名称默认为空(因为选择器的第一部分变为函数名称)此规则不再适用,您必须指定它。下划线简单地说,没有外部名称。因此,您的方法名称已正确转换为Objective-C的选择器。

由于mapView,函数名称_不会添加外部名称,因此它是mapView:。然后它会添加下一个外部参数名称renderFor,其中mapView:renderFor,然后是参数名称overlay,将其大写为Overlay,这会导致mapView:renderForOverlay: } - 正确的选择器。

非常简单,非常简单。另一个让Swift中的东西变得简单易用的功能。比如Objective-C

更容易

答案 1 :(得分:1)

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

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

correct signature是:

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

注意区别(&#34;下划线&#34;)。

如果您的代码不在显式声明符合MKMapViewDelegate的类或扩展声明中,则会出现另一个可能的问题。 Swift 3非常挑剔。 (你没有给我足够的背景知道你是否正确得到那个部分。)

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