辞書のタイプが<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から、具体的な拡張を行うことができます。つまり:
extension Dictionary where Key == String {}
具体的なジェネリックを含む具体的な型を適合させることはできません。
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
に適切に変換します。
小さなメモ:辞書は既に
Key
にHashable
になるように制約を入力しているため、元の制約は何も追加していませんでした。
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"]
Swift 3アプローチ
extension Dictionary where Key: ExpressibleByStringLiteral, Value: AnyObject
StringLiteralConvertibleは非推奨になり、ExpressibleByStringLiteralに置き換えられました。
文字列添え字付き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)
}
}
Swiftの更新
これは、ExpressibleByStringLiteral
にKey
を、Any
にValue
を使用した私の例です。
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に変換できますが、どちらも機能します。その後、辞書または他の特定のタイプとして展開します。
したがって、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) {
...
}
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 ""
}
}
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)
}
}
}