编译器错误:使用Objective-C选择器的方法与先前使用相同Objective-C选择器的声明冲突

时间:2015-04-05 13:19:12

标签: swift

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

Developing iOS 8 Apps with Swift - 2. More Xcode and Swift, MVC

在讲课之后,我达到了一点(据我所知),我的代码与视频中的代码相同,但在我的系统上,我遇到了编译错误。经过大量的试验和错误后,我设法将我的代码减少到两个例子,其中一个产生错误,另一个或不产生错误,但我不知道究竟是什么原因导致错误或如何解决它。

产生错误的代码是:

import UIKit

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

    func perform(operation: (Double, Double) -> Double) {
    }
}

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

  

方法'执行'与Objective-C选择器'执行:'与先前声明的冲突与相同的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版本上运行的版本。

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

6 个答案:

答案 0 :(得分:238)

我自己也参加了斯坦福大学的课程,我也被困在这里很长一段时间,但经过一番搜索后,我发现了一些来自这里的东西:Xcode release notes它提到了以下内容:

  

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运行时:

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

覆盖暴露的方法   私有子类中的Objective-C不被推断为@objc,   导致Swift编译器崩溃。明确添加@objc   属于任何这样的重写方法。 (19935352)

     

在a中快速使用Open Quickly时,SDK中的符号不​​可用   使用Swift的项目或工作区。 (20349540)

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

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

答案 1 :(得分:142)

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

答案 2 :(得分:108)

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

func methodOne(par1, par2) {...}

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

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

func methodOne() {...}

@nonobjc
func methodOne() {...}

答案 3 :(得分:17)

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

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

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


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

答案 4 :(得分:5)

来自https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html" Xcode 6.3发行说明" - > "迅速的语言变化"你找到了

  

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

答案 5 :(得分:2)

由于两个方法具有相同的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 {