编译器错误:使用Objective-Cselect器的方法与以前的声明相冲突

我开始学习斯威夫特,一直在关注YouTube上斯坦福大学的video讲座。 如果你有兴趣或有帮助,这里是一个链接(虽然不需要理解我的问题):

使用Swift开发iOS 8应用程序 – 更多Xcode和Swift,MVC

在听讲座后,我得到了一个点(据我所知),我的代码与video中的代码完全相同,但是在我的系统中出现了编译器错误。 经过大量的试验和错误,我设法减less我的代码为两个例子,其中一个产生一个错误,另一个或没有,但我不知道究竟是什么导致错误或如何解决它。

造成错误的代码是:

import UIKit class BugViewController: UIViewController { func perform(operation: (Double) -> Double) { } func perform(operation: (Double, Double) -> Double) { } } 

这会产生以下编译器错误:

使用Objective-Cselect器“执行”的方法“执行”与先前的声明与相同的Objective-Cselect器冲突

通过简单地删除UIViewController的子分类代码编译:

 import UIKit class BugViewController { func perform(operation: (Double) -> Double) { } func perform(operation: (Double, Double) -> Double) { } } 

其他一些可能相关或不相关的信息:

  • 我最近升级到优胜美地。
  • 当我安装Xcode时,我最终得到了一个Beta版本(版本6.3(6D543q)),因为(如果我没有记错的话),这是我需要在我的OS X版本上运行的版本。

我有一半希望这是编译器中的一个错误,否则这对我没有任何意义。 任何帮助非常感激地收到!

Objective-C不支持方法重载,你必须使用不同的方法名称。 当你inheritance了UIViewController的时候,你inheritance了NSObject并且把这个类交给了Obj-C。 另一方面,Swift确实支持重载,这就是为什么当你删除inheritance时它工作的原因。

我自己也参加了斯坦福大学的课程,并且在这里呆了很长一段时间,但经过一番search之后,我发现了一些东西: Xcode发行说明和下面提到的东西:

Swift 1.2严格检查@objc方法和初始化程序的基于types的重载,Objective-C不支持它。

 // Has the Objective-C selector "performOperation:". func performOperation(op: NSOperation) { /* do something */ } // Also has the selector "performOperation:". func performOperation(fn: () -> Void) { self.performOperation(NSBlockOperation(block: fn)) } 

这个代码在从Swift中调用的时候可以工作,但是如果从Objective-C调用的话,这个代码很容易崩溃。 为了解决这个问题,使用Objective-C不支持的types来防止Swift编译器将成员暴露给Objective-C运行时:

  • 如果有意义,将该成员标记为私有,以禁用@objc的推断。
  • 否则,请使用具有默认值的伪参数,例如:_ nonobjc:()=()。 (19826275)

在私有子类中暴露给Objective-C的方法的覆盖不会被推断为@objc,从而导致Swift编译器崩溃。 显式地将@objc属性添加到任何这样的覆盖方法。 (19935352)

在使用Swift的项目或工作区中使用“快速打开”时,SDK中的符号不​​可用。 (20349540)

我所做的只是在覆盖方法的前面添加“private”,像这样:

  private func performOperation(operation: Double -> Double) { if operandStack.count >= 1 { displayValue = operation(operandStack.removeLast()) enter() } } 

由于已经被回答,ObjC不支持方法重载(两个同名的方法),而在Swift 2中Xcode 7下有两个选项来解决这类问题。 一个选项是使用属性重命名该方法: @objc(newNameMethod:)

 func methodOne(par1, par2) {...} @objc(methodTwo:) func methodOne(par1) {...} 

在Xcode 7+中解决这个问题的另一个select是将@nonobjc属性应用于任何方法,下标或初始化

 func methodOne() {...} @nonobjc func methodOne() {...} 

问题是UIViewController是一个@objc类。 当从UIViewControllerinheritance时, BugViewController也是一个@objc类。

这意味着它必须符合Objective-Cselect器的规则(方法的名称)。 func perform(operation: (Double) -> Double)func perform(operation: (Double, Double) -> Double)都有相同的select器@selector(perform:) 。 这是不允许的。

为了解决这个问题,使用不同的名称:如func perform1(operation: (Double) -> Double)func perform2(operation: (Double, Double) -> Double)


我认为处理这个最好的方法是给你的perform()方法更多的描述性名称。 这些方法是做什么的? 他们如何改变视图控制器的状态? 查看其他的UIViewController方法来获得方法命名样式的感觉,或者读取方法名称应该在类中performance和唯一

https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html下的“Xcode 6.3发行说明” – >“Swift Language Changes”find

Swift现在检测到Swifttypes系统中的重载和重写之间的差异以及通过Objective-C运行时看到的有效行为。

由于有两个具有相同Obj-C签名的方法,我得到了同样的错误:

 static func prepareForUpSyncing(obj : NSManagedObject!) -> Bool static func prepareForUpSyncing(objs : [NSManagedObject]!) -> Bool 

我不想把它们中的一个标记为@nonobjc,因为在运行时可能导致不可预期的后果。 (如果没有可能,有人可以纠正我)

通过使用Swift的外部参数名称function(我将外部名称与本地名称相同)parsing到第二个方法,这有效地更改了Obj-c方法签名:

 static func prepareForUpSyncing(objs objs : [NSManagedObject]!) -> Bool {