在Swift 1.2中,声明不能既是“最终”也是“dynamic”错误

下面的value声明

 import Foundation class AAA: NSObject { func test2() { self.dynamicType } } extension AAA { static let value = 111 } 

导致以下编译错误

 A declaration cannot be both 'final' and 'dynamic' 

为什么会发生这种情况,我该如何处理?

我正在使用Swift 1.2(Xcode 6.3.1 6D1002内的版本)

出现这个问题是因为Swift试图为Obj-C兼容性的静态属性生成一个dynamic访问器,因为这个类inheritance自NSObject

如果你的项目只在Swift中,而不是使用var访问器,你可以通过Swift 2.0中的@nonobjc属性来避免这个问题:

 import Foundation class AAA: NSObject {} extension AAA { @nonobjc static let value = 111 } 

如果你的课程满足这些条件,你将会得到这个错误。

  • NSObject
  • 有一个static let场。
  • 通过dynamicType从实例方法访问字段。

我不知道为什么会发生这种情况,但是您可以尝试这种解决方法。

 static var value: Int { get { return 111 } } 

或者更短的forms。

 static var value: Int { return 111 } 

使用static var { get }而不是static let


虽然在上面的例子中,属性getter的closures和调用成本很可能被LLVM优化器消除,但是您可能要明确地避免它。

如果您担心这种价值计算成本,您可以创build一次并像这样caching。

 static var value: Int { return cache } private let cache = getTheNumber() 

或者像这样,如果你想完全隐藏它的caching。

 static var value: Int { struct Local { static let cache = getTheNumber() } return Local.cache } 

我也有这个错误。

我的问题只是一个迅速扩展的静态variables。

 extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate { static var timeIntervalFormatter = NSDateComponentsFormatter() } 

把它移到类实现中解决了我的问题。

我只是偶然发现了一个不同的原因相同的问题,并希望在这里发布给其他人遇到相同的无用的错误信息。

覆盖扩展中定义的计算variables的最后一个类也会导致此错误。 它虽然适用于函数,因此看起来像一个编译器错误。

 // at line 0: a declaration cannot be both 'final' and 'dynamic' import UIKit extension UIViewController { var test: Int { return 0 } } final class TestController: UIViewController { override var test: Int { return 1 } } 

我通过将静态声明移动到扩展中定义的新结构中解决了这个问题。

所以,而不是这个:

 extension NSOperationQueue { static var parsingQueue : NSOperationQueue = { let queue = NSOperationQueue() queue.maxConcurrentOperationCount = 1 return queue }() } 

我有这个:

 extension NSOperationQueue { struct Shared { static var parsingQueue : NSOperationQueue = { let queue = NSOperationQueue() queue.maxConcurrentOperationCount = 1 return queue }() } } 

您可以将其标记为私人以防止此错误。 如果你想暴露它,你可以把它包装在一个公共的function:

 extension AAA { private static let value = 111 public func getDatValue() -> Int { return AAA.value } } 

就我而言,我只是在扩展本身中引用属性,所以没有必要公开它。

作为@ Eonil的回答略有改善, get没有必要:

 static var value: Int { return 111 }