任何想法为什么我的Swift 3 iOS应用程序,这个
@objc(mapView:rendererForOverlay:) func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
触发器, 但如果我用上面的语句替换
func mapView(mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
不会触发。
答案 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 {
func mapView(_ mapView: MKMapView,
rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
注意区别(&#34;下划线&#34;)。
如果您的代码不在显式声明符合MKMapViewDelegate的类或扩展声明中,则会出现另一个可能的问题。 Swift 3非常挑剔。 (你没有给我足够的背景知道你是否正确得到那个部分。)
@objc
声明通过将此函数明确地桥接到Objective-C来解决这两个问题。但是如果你在两个方面做得都正确,Swift会为你做桥接,而@objc
则不需要。