web-dev-qa-db-ja.com

<String、AnyObject>の辞書の拡張

辞書のタイプが<String、AnyObject>である辞書拡張機能を作成しようとしています。

多くの場所を見て、異なるアプローチを試みましたが、どれもうまくいかなかったようです。これはそのうちの1つです。

extension Dictionary where <String, AnyObject>{
    var jsonString:String {
        return ""
    }
}

何らかの理由で実際に動作しなかった別の方法:

extension Dictionary where Key:Hashable, Value:AnyObject {

    var jsonString:String {

        do {
           let stringData = try NSJSONSerialization.dataWithJSONObject(self, options: NSJSONWritingOptions.PrettyPrinted)
            if let string = String(data: stringData, encoding: NSUTF8StringEncoding){
                return string
            }
        }catch _ {

        }
        return ""
    }
}

わかりました:引数タイプ 'Dictionary'は 'AnyObject'の予想されるタイプに準拠していません

> = 3.1

3.1から、具体的な拡張を行うことができます。つまり:

extension Dictionary where Key == String {}

<3.1

具体的なジェネリックを含む具体的な型を適合させることはできません。

extension Dictionary where Key == String

ただし、ディクショナリはシーケンスに準拠しており、具体的なジェネリックを含むプロトコルタイプを準拠できるため、次のことが可能です。

extension Sequence where Iterator.Element == (key: String, value: AnyObject) {
    func doStuff() {...

それ以外の場合は、文字列が次のように適合するプロトコルにキーを制限できます。

extension Dictionary where Key: StringLiteralConvertible, Value: AnyObject {
    var jsonString: String {
        return ""
    }
}

更新された回答に従って。 JSONシリアル化にはオブジェクトが必要です。Swift辞書は構造体です。NSDictionaryに変換する必要があります。Keyを指定してNSObjectに準拠する必要があります。 NSDictionaryに適切に変換します。

小さなメモ:辞書は既にKeyHashableになるように制約を入力しているため、元の制約は何も追加していませんでした。

extension Dictionary where Key: NSObject, Value:AnyObject {

    var jsonString:String {

        do {
            let stringData = try NSJSONSerialization.dataWithJSONObject(self as NSDictionary, options: NSJSONWritingOptions.PrettyPrinted)
            if let string = String(data: stringData, encoding: NSUTF8StringEncoding){
                return string
            }
        }catch _ {

        }
        return ""
    }
}

拡張機能にアクセスするには、辞書がこのタイプに準拠している必要があることに注意してください。

let dict = ["k" : "v"]

タイプは[String : String]になります。そのため、次の宣言を明示的に行う必要があります。

let dict: [NSObject : AnyObject] = ["k" : "v"]
87
Logan

Swift 3アプローチ

extension Dictionary where Key: ExpressibleByStringLiteral, Value: AnyObject

StringLiteralConvertibleは非推奨になり、ExpressibleByStringLiteralに置き換えられました。

6
Aidan Malone

文字列添え字付きDictionaryにカスタムプロパティを追加しようとしている人のために、@ Loganが提供する答えに追加することも可能です(このSO質問):

extension Dictionary where Key: StringLiteralConvertible {

    var somePropertyThatIsAColor:UIColor? {
        get {
            return self["someKey"] as? UIColor
        }
        set {
            // Have to cast as optional Value
            self["someKey"] = (newValue as? Value)
    }

}
4
Jason Henderson

Swiftの更新
これは、ExpressibleByStringLiteralKeyを、AnyValueを使用した私の例です。

extension Dictionary where Key: StringLiteralConvertible, Value: Any {
    var jsonString: String? {
        if let dict = (self as AnyObject) as? Dictionary<String, AnyObject> {
            do {
                let data = try JSONSerialization.data(withJSONObject: dict, options: JSONSerialization.WritingOptions(rawValue: UInt.allZeros))
                if let string = String(data: data, encoding: String.Encoding.utf8) {
                    return string
                }
            } catch {
                print(error)
            }
        }
        return nil
    }
}

そして、私はこれを次のように使用します:

let dict: Dictionary<String, AnyObject> = [...]
let jsonString = dict.jsonString

自分自身をAnyObjectまたはNSObjectに変換できますが、どちらも機能します。その後、辞書または他の特定のタイプとして展開します。

3
Jonauz

したがって、Dictionaryは次のとおりです。

public struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible {..}

プロトコル拡張はどうですか? :D

extension CollectionType where Self: DictionaryLiteralConvertible, Self.Key == String, Self.Value == AnyObject, Generator.Element == (Self.Key, Self.Value) {
...
}
2
Andrei Popa

Swift 3で提供されたソリューションを動作させることはできませんでしたが、DictionaryとNSDictionaryの間のブリッジを利用することで、この動作を実現できました。

extension NSDictionary {

    var jsonString:String {

        do {
            let stringData = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
            if let string = String(data: stringData, encoding: .utf8) {
                return string
            }
        }catch _ {

        }
        return ""
    }
}
1
Drew C

Dictionaryの代わりに[String:Any]を使用する人は誰でも以下の拡張子を使用できます

extension Dictionary where Key == String, Value == Any {

    mutating func append(anotherDict:[String:Any]) {
        for (key, value) in anotherDict {
            self.updateValue(value, forKey: key)
        }
    }
}
0
Dhaval H. Nena