在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 }