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

时间:2015-04-23 05:46:25

标签: swift compiler-errors

The declaration of value below

import Foundation

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

causes the following compilation error

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

Why does this happen, and how can I deal with this?

I am using Swift 1.2 (the version shipped within Xcode 6.3.1 6D1002)

7 个答案:

答案 0 :(得分:224)

出现此问题是因为Swift正在尝试为Obj-C兼容性生成静态属性的动态访问器,因为该类继承自NSObject

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

import Foundation

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

答案 1 :(得分:58)

You will get this error if your class satisfies these conditions.

  • Subclassed from NSObject.
  • Has a static let field.
  • Accesses the field from an instance method via dynamicType.

I don't know why this happens, but you can try this workaround.

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

Or in shorter form.

static var value: Int {
    return 111
}

Use static var { get } instead of static let.


Though property getter closure and its calling cost is very likely to be eliminated by LLVM optimiser in above example, you might want to avoid it explicitly.

If you're concerned about such value calculation cost, you can create it once and cache like this.

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

Or like this if you want to hide the cache it completely.

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

答案 2 :(得分:18)

我也有这个错误。

我的问题只是一个快速扩展中的 static var

extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate {

    static var timeIntervalFormatter = NSDateComponentsFormatter()

}

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

答案 3 :(得分:7)

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

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

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

答案 4 :(得分:7)

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

所以不要这样:

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

答案 5 :(得分:0)

您可以将其标记为私有以防止此错误。如果要公开它,可以将其包装在公共函数中:

extension AAA {

    private static let value = 111

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

就我而言,我只引用了扩展本身的属性,因此不需要公开它。

答案 6 :(得分:0)

@Eonil's answer略有改善,vendor/autoload.php没有必要:

get