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

SwiftCompiler Errors

Swift Problem Overview


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)

Swift Solutions


Solution 1 - Swift

This issue arises because Swift is trying to generate a dynamic accessor for the static property for Obj-C compatibility, since the class inherits from NSObject.

If your project is in Swift only, rather than using a var accessor you can avoid the issue via the @nonobjc attribute in Swift 2.0:

import Foundation

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

Solution 2 - Swift

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 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 existence of cache completely.

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

Solution 3 - Swift

I had this error too.

My issue was just a static var in a swift extension.

extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate {

    static var timeIntervalFormatter = NSDateComponentsFormatter()
 
}

Moving it to the class implementation resolved the problem for me.

Solution 4 - Swift

I just stumbled over the same issue with a different cause and would like to post it here for other people experiencing the same useless error message.

A final class which overrides a computed variable defined in an extension also causes this error. It works for functions though and thus looks like a compiler 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 }
}

Solution 5 - Swift

I solved this issue by moving the static declaration into the new struct I defined in the extension.

So instead of this:

extension NSOperationQueue {
    static var parsingQueue : NSOperationQueue = {
        let queue = NSOperationQueue()
        queue.maxConcurrentOperationCount = 1
        return queue
        }()
}

I have this:

extension NSOperationQueue {        
    struct Shared {
        static var parsingQueue : NSOperationQueue = {
            let queue = NSOperationQueue()
            queue.maxConcurrentOperationCount = 1
            return queue                
            }()
    }
}

Solution 6 - Swift

You can mark it as private to prevent this error. If you want to expose it, you can wrap it in a public function:

extension AAA {

    private static let value = 111

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

In my case, I only referenced the property in the extension itself, so there was no need to expose it.

Solution 7 - Swift

As a slight improvement over @Eonil's answer, the get not necessary:

static var value: Int { return  111 }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioneonilView Question on Stackoverflow
Solution 1 - SwiftAlex PretzlavView Answer on Stackoverflow
Solution 2 - SwifteonilView Answer on Stackoverflow
Solution 3 - SwiftJulianMView Answer on Stackoverflow
Solution 4 - SwiftfluidsonicView Answer on Stackoverflow
Solution 5 - SwiftVojtaStavikView Answer on Stackoverflow
Solution 6 - Swiftpulse4lifeView Answer on Stackoverflow
Solution 7 - SwiftYuchenView Answer on Stackoverflow