声明不能同时为';最终';和';动态';Swift 1.2中的错误

声明不能同时为';最终';和';动态';Swift 1.2中的错误,swift,compiler-errors,Swift,Compiler Errors,下面的值声明 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

下面的
值声明

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中附带的版本)

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

  • 子类化自
    NSObject
  • 有一个
    静态let
    字段
  • 通过
    dynamicType
    从实例方法访问字段
我不知道为什么会发生这种情况,但您可以尝试这种解决方法

static var value: Int {
    get {
        return 111
    }
}
或者以较短的形式

static var value: Int {
    return 111
}
使用
static var{get}
而不是
static let


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

如果您关心这样的值计算成本,您可以创建一次,然后像这样缓存

static var value: Int {
    return cache
}
private let cache = getTheNumber()
或者像这样,如果你想完全隐藏缓存的存在

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

我只是因为不同的原因偶然发现了同一个问题,我想在这里为其他遇到同样无用错误消息的人发布它

覆盖扩展中定义的计算变量的最终类也会导致此错误。但它适用于函数,因此看起来像一个编译器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 }
}
我也有这个错误

我的问题只是swift扩展中的一个静态变量

extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate {

    static var timeIntervalFormatter = NSDateComponentsFormatter()

}

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

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

extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate {

    static var timeIntervalFormatter = NSDateComponentsFormatter()

}
因此,与此相反:

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兼容性的静态属性生成动态访问器,因为该类继承自
NSObject

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

import Foundation

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

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

extension AAA {

    private static let value = 111

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

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

作为一个轻微的改进,get不需要:

static var value: Int { return  111 }

我的项目有一些Objective-C文件,但是没有一个代码与这个类的实例交互(这里是
AAA
),所以我想我清楚了?如果使用纯Swift代码库,这应该是选择的答案。我试图将静态(类)变量添加到
NSManagedObject
子类中。这个修好了!我是唯一一个发现此修复程序完全破坏Xcode 7.3的SourceKitService的人吗?这会生成一个计算属性,每次访问时都会重新计算该属性。在这种情况下,这可能不太重要,但我认为值得一提的是,没有人将此解决方案用于更大的对象。@NickPodratz这也是一个计算属性吗
private static let\u value:Int=111
static var value:Int{return\u value}
它没有
get{
但是如果我使用
var
而不是
let
@hashier,编译器会提到一些关于computed属性的内容。在大括号内创建一个闭包,在这种情况下,
get
是隐式的。相反,可以将闭包的结果赋给变量,以便只调用一次闭包:<代码>let值:Int={return 111}()
。结尾的括号称为闭包。但请注意,这是一个存储属性,因此在扩展中不可用。同意@NickPodratz的评估。虽然这解决了OP提到的错误,因此这是一个合法的答案,但如果您希望变量实际上是静态的,它不会提供任何好处(这似乎是重点)。在这种情况下,Alex的答案更好(假设为纯Swift),从Xcode 7.3.1开始,触发错误不需要
func test2
声明。只需将该静态变量放入另一个更好的命名结构中即可