2017-08-31 37 views
0

這可能最好用一個用例來解釋。OptionSet與每個選項的關聯值

我有一個記錄類。它將消息記錄到輸出級別。

class Logger { 
    var outputs: OutputOptions 
    var filter: Level 

    func log(_ message: String, at level: Level) { 
     if level <= self.filter { 
     outputs.log(message) 
     } 
    } 
} 

可能的輸出由定義OptionSet並確定要它輸出(的NSLog,Instabug等)消息應該被記錄。 OptionSet在這裏很不錯,因爲我可以定義選擇多個輸出並輕鬆檢查在記錄時選擇哪個。

struct OutputOptions: OptionSet { 
    let rawValue: Int 

    static let console = OutputOptions(1 << 0) 
    static let instabug = OutputOptions(1 << 1) 

    func log(_ message: String) { 
     if self.contains(.console) { 
      NSLog(message) 
     } 

     // etc 
    } 
} 

水平是通過枚舉定義的,並且表示消息的水平,如錯誤,警告,信息等記錄器可以過濾掉消息高於某一水平,如果我們不感興趣得到一個冗長的輸出。記錄器的過濾器也被設置爲一個級別。

enum Level: Int {none, no logs are shown. */ 
    case none = 0 
    case error = 1 
    case warning = 2 
    case info = 3 
    case verbose = 4 
} 

我想輸出選項和級別相結合以某種方式,讓我指定某些輸出可過濾消息到一定的水平,而其他輸出可以過濾到其他級別。例如,我想將詳細消息記錄到控制檯,但只有錯誤發送給Instabug。從表面上看,OptionSets看起來像可組合的枚舉,所以我的思想立即轉到相關的值。如果每個選項可以有一個相關的過濾級別,我可以設置一個記錄器的輸出是這樣的:

let logger = Loggger() 
logger.outputs = [.console(filter: .verbose), .instabug(filter: .error)] 

在試圖得到這個工作,我添加了一個過濾器屬性設置OutputOptions。我選擇現在這個樣子:

struct OutputOptions: OptionSet { 
    let rawValue: Int 
    var filter: Level = .info 

    init(rawValue: Int, filter: Level) { 
     self.rawValue = rawValue 
     self.filter = filter 
    } 

    static func console(filter: Level = .info) { 
     return OutputOptions(rawValue: 1 << 0, filter: filter) 
    } 

    // etc 

,但我無法弄清楚如何訪問一個元素的過濾器變量log。根據我對枚舉的經驗,我本可以期望能夠做到

func log(_ message: String, at level: Level) { 
     if self.contains(.console(let filter)) { // <== does not compile! 
     if level <= filter { 
      NSLog(message) 
     } 
     } 
    } 
} 

但是這並不能編譯。事實上,它看起來像filter屬性沒有爲每個選項單獨定義,而是爲整個選項集。

SO:有沒有辦法將值與選項集中的各個選項相關聯?

回答

1

但是,這並沒有編譯。實際上,它看起來像沒有爲每個選項單獨定義過濾器屬性,而是針對整個選項集。

這是因爲OptionSet本身不是集合。如果我有以下OptionSet:

struct MyOptions: OptionSet { 
    let rawValue: Int 

    static let foo = MyOptions(1 << 0) 
    static let bar = MyOptions(1 << 1) 
} 

,然後我作出這樣的設置使:

let opts: MyOptions = [.foo, .bar]

我實際上並不帶有兩個MyOptions實例的集合。相反,我有一個MyOptions的新實例,它的rawValue設置爲(.foo.rawValue | .bar.rawValue) -i.e. 3.一旦opts被創建,原來的兩個MyOptions實例就會被丟棄。

同樣,您的logger.outputs將是OutputOptions的一個實例,其中rawValue 3和默認值爲filter

因此,用OptionSet做你想做的事情是不可能的。

+0

有道理。也許我應該放棄OptionSet的好處,然後讓我的選項成爲一個枚舉數組。 –

相關問題