在 Swift 1.2中,声明不能同时是“ final”和“ 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.16D1002中提供的版本)

14779 次浏览

如果您的类满足这些条件,您将得到此错误。

  • NSObject子类化。
  • Has a static let field.
  • 通过 dynamicType从实例方法访问字段。

我不知道为什么会这样,但你可以试试这个变通方法。

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

或者简称。

static var value: Int {
return 111
}

使用 static var { get }代替 static let


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

如果您关心这样的价值计算成本,您可以创建它一次并像这样缓存。

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

如果您想完全隐藏缓存的存在,也可以这样做。

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

我只是偶然发现了同样的问题,但原因不同,我想把它贴在这里,以便其他人经历相同的无用的错误消息。

A final class which overrides a computed variable defined in an extension also causes this error. It works for functions though and thus looks like a compiler bug.

// 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 NotificationsViewController: UITableViewDataSource , UITableViewDelegate {


static var timeIntervalFormatter = NSDateComponentsFormatter()


}

将它移动到类实现为我解决了这个问题。

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

所以不是这样:

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

I have this:

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

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

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

import Foundation


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

可以将其标记为 private,以防止出现此错误。如果要公开它,可以将它包装在一个公共函数中:

extension AAA {


private static let value = 111


public func getDatValue() -> Int {
return AAA.value
}
}

在我的例子中,我只引用了扩展本身中的属性,所以没有必要公开它。

作为对 @ Eonil 的回答的轻微改进,get不是必须的:

static var value: Int { return  111 }