首页 文章

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

提问于
浏览
50

Swift只允许字典包含单个类型 .

这是Swift书中的定义:

字典是一个存储多个相同类型值的容器[...]它们与Objective-C的NSDictionary和NSMutableDictionary类不同,后者可以使用任何类型的对象作为其键和值,并且不提供有关这些物体的本质 .

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

想象一下,我们有一个 plist ,它包含String,Array和Dictionary项目 . 如果我只允许持有相同类型的项目(字符串,数组等),那么我将如何使用存储在plist中的不同类型的项目?

如何在Swift中的同一个字典中放入不同的类型?

7 回答

  • 0

    您可以使用 Any 类型实现类似plist的嵌套结构,用于字典值,即Swift 's somewhat counterpart to Objective-C' s id 类型,但也可以保存值类型 .

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

    编辑:

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

  • -2

    正如已经建议的那样,你可以使用 Any 类型来表示一个真正凌乱的plist字典's values. But then how do you work with the data? Cast every value any time you look it up from the dictionary? That' . 一个更好,更类型安全的方法来模拟一个plist将是利用Swift 's enums, also known as algebraic data types or discriminated unions. They let you specify exactly what types are permitted in the dictionary and avoid ever having to cast. Here'的一个实现,解释说:

    // 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'最终只能是这些类型中的一种 . 所以我们创建一个枚举,让我们指定它 .

    // 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值对的字典 . 上面的枚举表达了这些约束,而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)):
        ...
    }
    

    请注意,有必要将递归数据结构包装在“框”(指向实际值的指针)中,以保持其大小有限 .

  • 2

    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
    
  • 11

    使用:Dictionary <String,AnyObject>

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

    像这样使用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
    

    希望这会好起来的 .

  • 90

    NSMutableDictionary to Dictionary works like a charm and will allow you to put different types in a Dictionary in the 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)
    
  • 1
    let dictionary : Dictionary = [
        "key": "value",
        "key2": 2,
        "key3": NSString(),
        2: "test",
    ]
    

    可以指定限制字典的类型

    let dictionary : Dictionary<String, String> = [
        "key": "value",
        "key2": 2, // This errors
    ]
    

相关问题