Объявление не может быть как "финальной", так и "динамической" ошибкой в Swift 1.2
Объявление 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)
Ответы
Ответ 1
Эта проблема возникает из-за того, что Swift пытается создать динамический аксессуар для статического свойства для совместимости с Obj-C, поскольку класс наследует от NSObject
.
Если ваш проект работает только в Swift, а не с помощью var
accessor, вы можете избежать проблемы с помощью атрибута @nonobjc
в Swift 2.0:
import Foundation
class AAA: NSObject {}
extension AAA {
@nonobjc static let value = 111
}
Ответ 2
Вы получите эту ошибку, если ваш класс удовлетворяет этим условиям.
- Подклассифицировано из
NSObject
.
- Имеет поле
static let
.
- Получает доступ к полю из метода экземпляра через
dynamicType
.
Я не знаю, почему это происходит, но вы можете попробовать это обходное решение.
static var value: Int {
get {
return 111
}
}
Или в более короткой форме.
static var value: Int {
return 111
}
Используйте static var { get }
вместо static let
.
Хотя свойство getter закрытия и его стоимость вызова, скорее всего, будут устранены оптимизатором LLVM в приведенном выше примере, вы можете явно избегать этого.
Если вас беспокоит такая стоимость расчета стоимости, вы можете создать ее один раз и кэшировать, как это.
static var value: Int {
return cache
}
private let cache = getTheNumber()
Или так, если вы хотите полностью скрыть кеш.
static var value: Int {
struct Local {
static let cache = getTheNumber()
}
return Local.cache
}
Ответ 3
У меня тоже была эта ошибка.
Моя проблема была просто статическим var в быстром расширении.
extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate {
static var timeIntervalFormatter = NSDateComponentsFormatter()
}
Перемещение его в реализацию класса разрешило проблему для меня.
Ответ 4
Я просто наткнулся на одну и ту же проблему по другой причине и хотел бы опубликовать ее здесь, чтобы другие люди столкнулись с одним и тем же бесполезным сообщением об ошибке.
Заключительный класс, который переопределяет вычисленную переменную, определенную в расширении, также вызывает эту ошибку. Он работает для функций, хотя и, следовательно, выглядит как ошибка компилятора.
// 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 }
}
Ответ 5
Я решил эту проблему, перемещая статическое объявление в новую структуру I, определенную в расширении.
Итак, вместо этого:
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
}()
}
}
Ответ 6
Вы можете пометить ее как конфиденциальную, чтобы предотвратить эту ошибку. Если вы хотите открыть его, вы можете обернуть его в открытую функцию:
extension AAA {
private static let value = 111
public func getDatValue() -> Int {
return AAA.value
}
}
В моем случае я ссылался только на свойство в самом расширении, поэтому нет необходимости его раскрывать.
Ответ 7
Как небольшое улучшение по сравнению с @Eonil answer, get
не нужно:
static var value: Int { return 111 }