2017-08-31 1 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) 
     } 
    } 
} 

可能出力は、optionによって定義され、(の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

しかし、それはコンパイルされません。実際、filterプロパティはオプションごとに別々に定義されているのではなく、オプションセット全体で定義されているようです。

は、optionが本当にセット、それ自体ではないためです。私は、次は、option持ちの場合:

struct MyOptions: OptionSet { 
    let rawValue: Int 

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

をして、私はそうのようにセットします:

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

を私は実際にそれで2つのMyOptionsのインスタンスのコレクションを持っていません。代わりにrawValue(.foo.rawValue | .bar.rawValue)-i.eに設定されたMyOptionsという新しいインスタンスがあります。元の2つのMyOptionsインスタンスは、optsが作成されるとすぐに破棄されます。

同様に、logger.outputsOutputOptionsのインスタンスになり、rawValue 3となり、デフォルト値はfilterになります。

したがって、OptionSetであなたが望むことをすることは実際にはできません。

+0

意味があります。たぶん私はOptionSetの利点を手放すし、私のオプションを列挙型の配列にしてください。 –

関連する問題