编译器错误:使用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
类。 当从UIViewController
inheritance时, 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 {