Swift 1.2 中的声明不能同时是 'final' 和 'dynamic' 错误

A declaration cannot be both 'final' and 'dynamic' error in Swift 1.2

下面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 中的版本)

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

  • 子class来自NSObject
  • 有一个 static let 字段。
  • 通过 dynamicType.
  • 从实例方法访问字段

我不知道为什么会这样,但您可以试试这个解决方法。

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

或更短的形式。

static var value: Int {
    return 111
}

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


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

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

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

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

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

我只是因不同的原因偶然发现了同样的问题,并想post在这里为遇到同样无用错误消息的其他人提供帮助。

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

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

我也有这个错误。

我的问题只是 swift 扩展中的 static var

extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate {

    static var timeIntervalFormatter = NSDateComponentsFormatter()

}

将其移至 class 实现解决了我的问题。

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

所以不是这个:

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                
            }()
    }
}

出现此问题是因为 Swift 正试图为静态 属性 生成动态访问器以实现 Obj-C 兼容性,因为 class 继承自 NSObject

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

import Foundation

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

您可以将其标记为私有以防止出现此错误。如果你想公开它,你可以将它包装在一个 public 函数中:

extension AAA {

    private static let value = 111

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

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

作为对 的轻微改进,get 没有必要:

static var value: Int { return  111 }