在Swift 1.2中,声明不能同时是“最终”和“动态”错误


123

声明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随附的版本)


func test2Xcode 7.3.1开始,不需要声明即可触发错误。
罗布·马诺夫(Rob Mayoff)


只需将静态变量放入另一个更好的命名结构中
onmyway133 '16

Answers:


224

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

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

import Foundation

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

我的项目有一些Objective-C文件,但是这些代码都没有与此类的实例交互(AAA此处),所以我想我很清楚吗?
Nicolas Miari 2015年

如果使用纯Swift代码库,这应该是选择的答案。
idzski 2015年

我试图将静态(类)变量添加到NSManagedObject子类。这样解决了!
Nicolas Miari '16

我是唯一发现此修复程序完全破坏SourceKitService for Xcode 7.3的人吗?
NoodleOfDeath '16

57

如果您的班级满足这些条件,则会收到此错误。

  • 从继承NSObject
  • 有一个static let领域。
  • 通过访问实例方法中的字段dynamicType

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

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

或更短的形式。

static var value: Int {
    return 111
}

使用static var { get }代替static let


尽管在上面的示例中,LLVM优化器很可能消除了属性获取器及其调用成本,但是您可能希望明确避免使用它。

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

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

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

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

5
这将产生一个计算属性,该属性将在每次访问时重新计算。对于这种情况,它可能并不太重要,但我认为值得一提,因为没有人将这种变通方法用于更大的对象。
Nick Podratz 2015年

@NickPodratz这也将是计算所得的属性吗?private static let _value: Int = 111 static var value: Int { return _value }它没有,get {但是如果我使用var而不是let
hashier

1
@hashier是。在花括号内创建一个闭合,get在这种情况下,它是隐式的。相反,您可以做的是将闭包的结果分配给变量,以便闭包仅被调用一次:let value: Int = { return 111 }()。最后的方括号称为闭包。但是请注意,这又是一个存储的属性,因此在扩展名中不可用。
Nick Podratz '16

同意@NickPodratz的评估。虽然这可以解决OP提及的错误,因此使这成为一个合法的答案,但是如果您希望变量实际上是静态的(这似乎很关键),则不会带来任何好处。在那种情况下,亚历克斯的答案更好(假设使用纯粹的Swift)
马特·朗

18

我也有这个错误。

我的问题只是快速扩展中的静态var

extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate {

    static var timeIntervalFormatter = NSDateComponentsFormatter()

}

将其移到类实现中可以为我解决问题。


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

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

0

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

extension AAA {

    private static let value = 111

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

就我而言,我仅在扩展本身中引用了该属性,因此无需公开它。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.