编译器错误:带有Objective-C选择器的方法与以前带有相同Objective-C选择符的声明冲突



我开始学习Swift,并一直在YouTube上关注斯坦福大学非常好的视频讲座。如果你感兴趣或有帮助,这里有一个链接(尽管理解我的问题不需要它):

用Swift-2开发iOS 8应用程序。更多Xcode和Swift,MVC

在听讲座的过程中,我的代码(据我所知)与视频中的代码完全相同,但在我的系统中,我出现了编译器错误。经过大量的尝试和错误,我已经设法将我的代码简化为两个例子,其中一个会产生错误,另一个不会,但我不知道是什么导致了错误,也不知道如何解决它

造成错误的代码是:

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

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

具有Objective-C选择器"perform:"的方法"perform"与具有相同Objective-C选择符的先前声明冲突

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

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

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

  • 我最近升级到约塞米蒂
  • 当我安装Xcode时,我最终得到了Beta版本(版本6.3(6D543q)),因为(如果我没记错的话)这是我在OS X版本上运行所需的版本

我有点希望这是编译器中的一个错误,否则这对我来说毫无意义。非常感谢您的帮助!

我自己也在参加Standford课程,我也在这里呆了很长时间,但经过一番搜索,我在这里找到了一些东西:Xcode发布说明,其中提到了以下内容:

Swift 1.2严格检查@objc基于类型的重载方法和初始化程序,这是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不支持阻止Swift编译器将成员暴露于Objective-C运行时:

  • 如果有意义,请将该成员标记为private以禁用@objc的推断
  • 否则,对于例如:_nonobjc:()=()。(19826275)

已公开方法的覆盖私有子类中的Objective-C不被推断为@objc,导致Swift编译器崩溃。显式添加@objc属性。(19935352)

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

我所做的只是在覆盖方法前面添加"private",如下所示:

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

Objective-C不支持方法重载,您必须使用不同的方法名称。当您继承UIViewController时,您继承了NSObject,并使类可与Obj-C互操作。另一方面,Swift确实支持重载,这就是为什么它在删除继承时有效。

正如已经回答的那样,ObjC不支持方法重载(两个同名方法),在Xcode 7下的swift 2中有两个选项可以解决这类问题。一种选择是使用属性重命名方法:@objc(newNameMethod:)

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

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

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

问题是UIViewController@objc类。从UIViewController继承时,BugViewController也是@objc类。

这意味着它必须符合Objective-C选择器(方法的名称)的规则。方法CCD_ 8和CCD_ 9都具有相同的选择器CCD_。这是不允许的。

要解决此问题,请使用不同的名称:如func perform1(operation: (Double) -> Double)func perform2(operation: (Double, Double) -> Double)


我认为处理此问题的最佳方法是为perform()方法提供更多描述性名称。这些方法的作用是什么?它们如何更改视图控制器的状态?查看其他UIViewController方法以了解方法命名的风格,或者阅读method Names Should Expressive and Unique Within a Class

Fromhttps://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html在"Xcode 6.3 Release Notes"->"Swift Language Changes"下,您可以找到

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

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

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

我不想将其中一个标记为@nonobjc,因为在运行时可能会出现无法预见的后果。(如果没有可能的话,有人可以纠正我)

通过使用Swift的外部参数名称功能(我将外部名称与本地名称相同)将其解析为第二种方法,这有效地更改了Obj-c方法签名:

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

相关内容

最新更新