首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Swift语言中将不同的类型放入字典?

如何在Swift语言中将不同的类型放入字典?
EN

Stack Overflow用户
提问于 2014-06-04 02:01:05
回答 7查看 55.6K关注 0票数 58

Swift只允许一个字典包含一个类型。

以下是取自Swift一书的定义:

字典是存储相同类型的多个值的容器

..。

它们不同于Objective-C的NSDictionaryNSMutableDictionary类,后者可以使用任何类型的对象作为它们的键和值,并且不提供关于这些对象的性质的任何信息。

如果是这样的话,我们将如何创建嵌套字典?

假设我们有一个包含String、Array和Dictionary项的plist。如果我只能保存相同类型的项目(字符串、数组等)。那么我如何使用存储在plist中的不同类型的项呢?

如何在Swift中将不同类型放在同一字典中?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2014-06-04 02:11:05

您可以对字典值使用Swift类型来实现类似plist的嵌套结构,该类型在某种程度上与Objective-C的id类型相对应,但也可以包含值类型。

代码语言:javascript
复制
var response = Dictionary<String, Any>()
response["user"] = ["Login": "Power Ranger", "Password": "Mighty Morfin'"]
response["status"] = 200

编辑:

Any似乎比AnyObject更好,因为在上面的代码中,response["status"]的类型是Swift.Int,而使用AnyObject的值类型时,它是__NSCFNumber

票数 98
EN

Stack Overflow用户

发布于 2014-06-05 11:17:07

正如所建议的,您可以使用Any类型来表示plist字典的值。但是,如何处理这些数据呢?在字典中查找时,是否对每个值进行强制转换?那真是太乱了。对plist建模的一种更好、更安全的方法是利用Swift的枚举,也称为代数数据类型或区分联合。它们允许您准确地指定字典中允许的类型,而不必进行强制转换。下面是一个实现,解释如下:

代码语言:javascript
复制
// 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中的每个“node”最终只能是这些类型中的一种。所以我们创建一个枚举,让我们指定这一点。

代码语言:javascript
复制
// 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基本上是键-值对的字典,每个值可以是原子值(即非集合);也可以是原子值的数组;也可以是字符串-plist值对的字典。上面的枚举表达了这些约束,类型别名为plist类型提供了一个易于记忆的名称。

给定上述类型,我们可以完全以类型安全的方式表示任何给定的plist,例如:

代码语言:javascript
复制
// 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,并涵盖所有可能性,而不需要任何类型转换。您正在消除一整类潜在的运行时错误。例如:

代码语言:javascript
复制
// 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)):
    ...
}

请注意,有必要将递归数据结构包装在一个'box‘(指向实际值的指针)中,以保持它们的大小有限。

票数 19
EN

Stack Overflow用户

发布于 2014-06-05 14:42:08

NSObject适用于我的情况,而"Any“不适用

代码语言:javascript
复制
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
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24021950

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档