声明不能同时是Swift 1.2中的"最终"和"动态"错误

Eon*_*nil 123 compiler-errors swift

声明value如下

import Foundation

class AAA: NSObject {
    func test2() {
        self.dynamicType
    }
}
extension AAA {
    static let value    =   111
}
Run Code Online (Sandbox Code Playgroud)

导致以下编译错误

A declaration cannot be both 'final' and 'dynamic'
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,我该如何处理?

我使用的是Swift 1.2(Xcode 6.3.1 6D1002中提供的版本)

Ale*_*lav 224

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

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

import Foundation

class AAA: NSObject {}
extension AAA {
    @nonobjc static let value = 111
}
Run Code Online (Sandbox Code Playgroud)


Eon*_*nil 58

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

  • 从中分类NSObject.
  • 有一个static let领域.
  • 从实例方法访问该字段dynamicType.

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

static var value: Int {
    get {
        return 111
    }
}
Run Code Online (Sandbox Code Playgroud)

或者是较短的形式.

static var value: Int {
    return 111
}
Run Code Online (Sandbox Code Playgroud)

static var { get }而不是static let.


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

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

static var value: Int {
    return cache
}
private let cache = getTheNumber()
Run Code Online (Sandbox Code Playgroud)

或者像这样,如果你想完全隐藏它的缓存.

static var value: Int {
    struct Local {
        static let cache = getTheNumber()
    }
    return Local.cache
}
Run Code Online (Sandbox Code Playgroud)

  • 这将生成一个计算属性,该属性将在每次访问时重新计算.对于这种情况,它可能并不重要,但我认为值得一提的是,没有人将此解决方法用于更大的对象. (5认同)

Jul*_*anM 18

我也有这个错误.

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

extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate {

    static var timeIntervalFormatter = NSDateComponentsFormatter()

}
Run Code Online (Sandbox Code Playgroud)

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


flu*_*nic 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 }
}
Run Code Online (Sandbox Code Playgroud)


Voj*_*vik 7

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

所以不是这样的:

extension NSOperationQueue {
    static var parsingQueue : NSOperationQueue = {
        let queue = NSOperationQueue()
        queue.maxConcurrentOperationCount = 1
        return queue
        }()
}
Run Code Online (Sandbox Code Playgroud)

我有这个:

extension NSOperationQueue {        
    struct Shared {
        static var parsingQueue : NSOperationQueue = {
            let queue = NSOperationQueue()
            queue.maxConcurrentOperationCount = 1
            return queue                
            }()
    }
}
Run Code Online (Sandbox Code Playgroud)