我开始学习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时,我最终得到了测试版(版本6.3 (6D543q)),因为(如果我没记错的话)这是我在OS X版本上需要运行的版本。

我一半希望这是编译器中的一个bug,否则这对我来说没有任何意义。任何帮助都非常感激!


当前回答

我得到了同样的错误,因为有两个方法具有相同的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 {

其他回答

我自己也在上斯坦福的课程,我也被困在这里很长一段时间,但经过一些搜索,我从这里找到了一些东西:Xcode发布说明,它提到了以下内容:

Swift 1.2 is strict about checking type-based overloading of @objc methods and initializers, something not supported by 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)) } This code would work when invoked from Swift, but could easily crash if invoked from Objective-C. To solve this problem, use a type that is not supported by Objective-C to prevent the Swift compiler from exposing the member to the Objective-C runtime: If it makes sense, mark the member as private to disable inference of @objc. Otherwise, use a dummy parameter with a default value, for example: _ nonobjc: () = (). (19826275) Overrides of methods exposed to Objective-C in private subclasses are not inferred to be @objc, causing the Swift compiler to crash. Explicitly add the @objc attribute to any such overriding methods. (19935352) Symbols from SDKs are not available when using Open Quickly in a project or workspace that uses Swift. (20349540)

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

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

从https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html下的“Xcode 6.3发布说明”->“Swift语言变化”你可以找到

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

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

我得到了同样的错误,因为有两个方法具有相同的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 {

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

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

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

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

func methodOne() {...}

@nonobjc
func methodOne() {...}