2015-01-03 18 views
10

私はDictionary拡張を実装しようとしており、オプションの値を扱いたいと思います。しかし、私が何をするにしても、[String: String?]辞書で自分のメソッドを使用すると、オプションで値をバインドすることができません。オプションの値を適切に扱う拡張機能をどのようにして辞書に書いていますか?書く方法任意の値を扱う辞書拡張子


次の拡張を検討:

extension Dictionary { 
    func someMethod() { 
     for (key, value) in self { 
      if let valueString = value as? String { 
       println(" \(key) = \(valueString)") 
      } else { 
       println(" \(key) = \(value) cannot be cast to `String`") 
      } 
     } 
    } 
} 

だから、次のコードを考えてみます。

let dictionary: [String: AnyObject?] = ["foo": "bar"] 
dictionary.someMethod() 

をそして、それが妙に私が非拡張を書くことができます

foo = Optional(bar) cannot be cast to `String` 

報告をdictを処理するメソッド任意の値を持つ非イオン性パラメータを返しますが、それをどのようにしてDictionaryの拡張子として扱うかわかりません。

+0

あなたが期待するように見えるとして、それが動作しない理由を私は説明することができます。 Optional、 'as'、' is'、 'as?'、 '=='(そして他のコンパレータ)には特別な意味があります:これは物事に適用されます。理由は 'なぜlet valueString = value as?文字列 'はコンパイル時に' value'が分からないことを期待しているようです。_is_ anオプションで、オプションに適用される 'as'の特別な意味を使用しません。 Optional _itself_をStringにキャストしようとしますが、もちろん失敗します。任意の_itself_を何かにキャストすることはできません。 – matt

+1

あなた自身が言っているように、Swiftはインスタントメソッドの使用を招待しているようですが、実際のパワーはトップレベルのグローバル関数にあります。メッシュを通して正しいタイプのみを可能にするジェネリックコンストレインを構築でき、それはそうだった。ディクショナリは一般的なものであり、ジェネリックに制約を追加することはできないため、エクステンション内のインスタンスメソッドでこれを行うことはできません。 – matt

答えて

4

これはリフレクションで行うことができます。

extension Dictionary 
{ 
    func someMethod() 
    { 
     for (key, value) in self 
     { 
      var valueRef = _reflect(value) 

      while valueRef.disposition == .Optional && valueRef.count > 0 && valueRef[0].0 == "Some" 
      { 
       valueRef = valueRef[0].1 
      } 

      if let valueString: String = valueRef.value as? String 
      { 
       print(" \(key) = \(valueString)") 
      } 
      else 
      { 
       print(" \(key) = \(value) cannot be cast to `String`") 
      } 
     } 
    } 
} 

let dictionary: [String : AnyObject?] = ["foo" : "bar"] 
dictionary.someMethod() 

戻り

foo = bar 

let dictionary: [String : AnyObject?] = ["foo" : nil] 
dictionary.someMethod() 

戻り

:あなたが既に持っているよりもはるかに多くのコードを必要としません。
let dictionary: [String : AnyObject?] = ["foo" : UIViewController()] 
dictionary.someMethod() 

戻り

foo = Optional(<UIViewController: 0x7fee7e819870>) cannot be cast to `String` 
0

':String?'を挿入すると問題は発生しません。次のようにvalueStringの直後に配置します。

extension Dictionary { 
    func someMethod() -> Bool { 
     for (key, value) in self { 
      if let valueString:String? = value as? String { 
       println(" \(key) = \(valueString)") 
      } else { 
       println(" \(key) = \(value) cannot be cast to `String`") 
       return false 
      } 
     } 
     return true 
    } 
} 

func doSomething() { 
    let dictionary: [String: AnyObject?] = ["foo": "bar"] 
    if dictionary.someMethod() { 
     println("no problems") 
    } else { 
     println("casting issues") 
    } 
} 
+1

興味深い。これを行うと失敗して「キャストできません」(つまり「true」を返しますが、値が指定されていても 'valueString'は常に' nil'です)。 – Rob

関連する問題