web-dev-qa-db-ja.com

Swift Language?

Swiftでは、辞書に1つのタイプのみを含めることができます。

Swift本から取った定義は次のとおりです。

辞書は、同じタイプの複数の値を格納するコンテナです

[...]

これらは、Objective-CのNSDictionaryおよびNSMutableDictionaryクラスとは異なります。これらのクラスは、あらゆる種類のオブジェクトをキーおよび値として使用でき、これらのオブジェクトの性質に関する情報を提供しません。

その場合、ネストされた辞書をどのように作成しますか?

String、Array、Dictionaryアイテムを保持するplistがあるとします。同じ種類のアイテム(文字列、配列など)のみを保持できる場合、plistに保存されている異なる種類のアイテムをどのように使用しますか?

Swiftの同じ辞書に異なるタイプを入れるにはどうすればよいですか?

50
lionserdar

辞書値にAny型を使用してplistのような入れ子構造を実現できます。これは、SwiftのObjective-Cのid型に多少対応していますが、値型も保持できます。

var response = Dictionary<String, Any>()
response["user"] = ["Login": "Power Ranger", "Password": "Mighty Morfin'"]
response["status"] = 200

編集:

AnyAnyObjectよりも優れているようです。なぜなら上記のコードではresponse["status"]はタイプSwift.IntAnyObjectの値型を使用している間は__NSCFNumber

92
MDJ

提案されているように、Any型を使用して、plist辞書の値を表すことができます。しかし、データをどのように使用しますか?辞書から検索するたびにすべての値をキャストしますか?それは本当に面倒です。 plistをモデル化するためのより良い、よりタイプセーフな方法は、代数的データ型または識別された共用体としても知られるSwiftの列挙を利用することです。これにより、辞書で許可される型を正確に指定し、キャストする必要がなくなります。以下に説明する実装を示します。

// An atomic (i.e. non-collection) data type in a plist.
enum PListNode {
  case PLN_String(String)
  case PLN_Integer(Int)
  case PLN_Float(Double)
  case PLN_Bool(Bool)
  case PLN_Date(CFDate)
  case PLN_Data(CFData)
}

最もアトミックなレベルでは、上記のデータ型のみがplistに保存されます。 plist内の各「ノード」は、最終的にこれらのタイプのoneのみになります。そのため、これを指定できる列挙型を作成します。

// A value that can be stored in a plist Dictionary's key-value pair.
enum PListValue {
  case PLV_Node(PListNode)
  case PLV_Array(PListNode[])
  case PLV_Dictionary(Dictionary<String, Box<PListValue>>)
}

typealias PList = Dictionary<String, Box<PListValue>>

Plistは基本的にキーと値のペアのディクショナリであり、各値はアトミック(非コレクション)値のいずれかです。または、原子値の配列にすることができます。または、string-plist値のペアの辞書にすることもできます。上記の列挙型はこれらの制約を表し、typealiasはplist型に覚えやすい名前を付けます。

上記の型が与えられれば、与えられたplistを完全に表現できます型保証された方法で

// Example translated from
// https://developer.Apple.com/library/Mac/documentation/Darwin/Reference/ManPages/man5/plist.5.html
let myPlist: PList = [
  "Year Of Birth": Box(PLV_Node(PLN_Integer(1965)))
, "Pets Names":    Box(PLV_Array([]))
, "Picture":       Box(PLV_Node(PLN_Data(...)))
, "City of Birth": Box(PLV_Node(PLN_String("Springfield")))
, "Name":          Box(PLV_Node(PLN_String("John Doe")))
, "Kids Names":    Box(
    PLV_Array([PLN_String("John"), PLN_String("Kyra")])
  )
]

ここでタイプセーフであるとは、switchステートメントを使用して特定のplistを処理し、キャストすることなくすべての可能性をカバーできることです。潜在的なランタイムエラーのクラス全体を排除しています。例えば。:

// See https://developer.Apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html#//Apple_ref/doc/uid/TP40014097-CH12-XID_189 for explanation
switch myPlist["Year Of Birth"] {
  case Box(.PLV_Node(let plvNodeValue)):
    ...
  case Box(.PLV_Array(let plvArrayValue)):
    ...
  case Box(.PLV_Dictionary(let plvDictionaryValue)):
    ...
}

再帰的なデータ構造を「ボックス」(実際の値へのポインタ)でラップして、サイズを制限する必要があることに注意してください。

13
Yawar

NSMutableDictionaryは次のように使用します。

var dictInfo : NSMutableDictionary = [ "lang_key": "1"]
    dictInfo["food_type"]     =   lbl_TypeOfFood.text
    dictInfo["search_text"]   =   txt_Search.text
    dictInfo["date"]          =   lbl_Date.text
    dictInfo["opening_hours"] =   lbl_OpeningHours.text

これがうまくいくことを願っています。

2
Alok

NSObjectは私の場合は動作しますが、「Any」は動作しません

var d:Dictionary<String,NSObject> = [:]
d["key1"] = "ddd"
d["key2"] = 111  //OK
NSLog("%@", d) //OK

var d2:Dictionary = Dictionary<String,Any>()
d2["key1"] = "ddd"
d2["key2"] = 111
NSLog("%@", d2) //I got error here
2
Soyoes

使用:辞書<文字列、AnyObject>

var dict: Dictionary<String, AnyObject> = [
    "number": 1,
    "string": "Hello",
]
1
iamamused

NSMutableDictionary to Dictionaryはチャームのように機能し、Swift Language:

let nsMutableDictionary = NSMutableDictionary()
nsMutableDictionary[NSFontAttributeName] = UIFont(name: "HelveticaNeue", size: 12.0)!
nsMutableDictionary[NSForegroundColorAttributeName] = UIColor.redColor()

let dictionary: Dictionary<NSObject, AnyObject> = nsMutableDictionary

self.attributedPlaceholder = NSAttributedString(string: textParam, attributes: dictionary)
0
King-Wizard