2015-04-23 41 views
120

value下面的聲明不能既是「最終」和「動態」錯誤雨燕1.2

import Foundation 

class AAA: NSObject { 
    func test2() { 
     self.dynamicType 
    } 
} 
extension AAA { 
    static let value = 111 
} 

聲明導致以下編譯錯誤

A declaration cannot be both 'final' and 'dynamic' 

爲什麼會發生這種情況,以及如何我可以處理這個嗎?

我用的雨燕1.2(在在Xcode 6.3.1 6D1002運版)

+0

是不需要的'FUNC test2'聲明來觸發錯誤,如7.3.1的Xcode的。 –

+1

[swift bug SR-993](https://bugs.swift.org/browse/SR-993) –

+0

只需將該靜態變量放入另一個更好的命名結構中 – onmyway133

回答

222

這個問題的產生是因爲斯威夫特正試圖生成靜態屬性的對象 - 兼容性動態訪問,因爲該類繼承自NSObject

如果你的項目是斯威夫特只,而不是使用var訪問你能避免通過在雨燕2.0 @nonobjc屬性問題:

import Foundation 

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

我的項目有一些Objective-C文件,但沒有一個代碼與這個類的實例交互(這裏是'AAA'),所以我想我明白了嗎? –

+0

如果使用純Swift代碼庫,這應該是選擇的答案。 – Skyboat

+0

我試圖添加靜態(類)變量到'NSManagedObject'子類。這固定它! –

57

如果你的類滿足這些條件,您將收到此錯誤。

  • 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 
} 
+5

這將生成一個計算屬性,該屬性將在每次訪問時重新計算。對於這種情況,可能無關緊要,但我認爲值得一提,因此沒有人使用此解決方法處理更大的對象。 –

+0

@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}()'。最後的括號稱爲閉包。但請注意,這是再次存儲的屬性,因此無法在擴展中使用。 –

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

我也有這個錯誤。

我的問題只是一個靜態變量迅速擴展。

extension NotificationsViewController: UITableViewDataSource , UITableViewDelegate { 

    static var timeIntervalFormatter = NSDateComponentsFormatter() 

} 

將其移至類實現爲我解決了問題。

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

在我而言,我只是引用在擴展本身的性質,所以沒有必要將其暴露。

0

由於超過@Eonil's answer略有改進,get沒有必要:

static var value: Int { return 111 }