我开始学习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,否则这对我来说没有任何意义。任何帮助都非常感激!


当前回答

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

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

其他回答

因为它已经被回答了,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选择器的规则(方法的名称)。方法func perform(operation: (Double) -> Double)和func perform(operation: (Double, Double) -> Double)都有相同的选择器@selector(perform:)。这是不允许的。

要解决这个问题,请使用不同的名称:如func perform1(操作:(Double) -> Double)和func perform2(操作:(Double, Double) -> Double)。


我认为最好的处理方法是给你的perform()方法更多描述性的名称。这些方法有什么用?它们如何改变视图控制器的状态?看看其他的UIViewController方法来感受一下方法命名的风格,或者阅读类中的方法名称应该是表达性和唯一性的

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

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

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

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