@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 {
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
中更容易
知道为什么我的 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 {
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
中更容易