为什么没有[String:AnyObject?]和[String:AnyObject]与swift编译器的类型相同?

时间:2016-03-25 13:34:29

标签: swift

从语义上讲,[String:AnyObject?][String:AnyObject]就行为方式而言是相同的,这意味着如果我访问未设置和设置的密钥,它们将返回相同的内容nil的键将从字典中删除该键。为什么他们认为不是同一类型?

编辑:我从答案中了解编译器观点的不同之处。我决定将以下代码放在操场上:

var optional = [String:AnyObject?]()
var regular = [String:AnyObject]()

//Some control keys
optional["controlkey"] = "valueoptional"
regular["controlkey"] = "valueRegular"

//Set the keys
optional["keyOptional"] = "valueoptional"
regular["keyRegular"] = "valueRegular"

//Unset the keys
optional["keyOptional"] = nil
regular["keyRegular"] = nil

for (key,val) in optional {
    print("key: \(key)\tval: \(val)")
}

for (key,val) in regular {
    print("key: \(key)\tval: \(val)")
}

令我惊讶的是,可选的没有打印设置为nil的密钥。 产出如下:

key: controlkey val: Optional(valueoptional) //The keys for the optional dictionary
key: controlkey val: valueRegular //The keys for the `regular` dictionary

为什么我设置为nil的密钥不显示?

5 个答案:

答案 0 :(得分:1)

因为从编译器的角度来看,可空类型和非可空类型不是同一个东西。恰好Dictionnary界面最终将它们混合在一起#34;在类似的实体中,但这与Dictionnary实现相关联,而不是类型系统。

编辑:您的更新会更改问题的上下文,但设置为nil是一种不理解我的方法。

答案 1 :(得分:1)

来自Apple文档:

  

Swift语言定义了后缀?作为语法糖   命名类型可选,在Swift标准中定义   库。

AnyObject类型?是一个包含两种情况的枚举,None和Some(Wrapped),用于表示可能存在或不存在的值。但AnyObject正在响应将要呈现的那个。

为字典中的键设置nil意味着删除元素本身。 尝试设置NSNull()

optional["keyOptional"] = NSNull()

答案 2 :(得分:1)

它们不同,因为您实际上可以将nil存储到[String:AnyObject?]中。您不能使用optional[key] = value(下标运算符)来执行此操作,因为它具有nil的特殊行为(删除值),但您可以执行此操作:

var optional: [String:AnyObject?] = ["test": nil]
optional.updateValue(nil, forKey: "test2")

print(optional) // ["test2": nil, "test": nil]

当然,从这样的词典中获取一个值:

print(optional["test"]) // Optional(nil)

导致双重可选Optional<Optional<AnyObject>>(或AnyObject??)并且与这些类型的交互很麻烦,因此您应该避免将nil存储到词典中。

答案 3 :(得分:0)

因为设置密钥nil会从字典中删除该密钥!来自documentation

  

读取自身中不存在的关键字nil。将nil写为给定键的值将从自身中删除该键

您无法将nil存储为字典值。如果您需要某些东西来表示虚无,请使用NSNull

optional["keyOptional"] = NSNull()
regular["keyRegular"] = NSNull()

答案 4 :(得分:0)

它们的类型不同,因为它们的类型不同;-)编译器就是这样的文字生物。

@Sulthan的答案是正确的,更完整的 - 直到我在自己的答案上发帖后才看到它。但是如果你在[String: AnyObject?]字典中查找一个键并且存在一个值,你将获得一个包含在一个可选项中的可选项 - 结果是一个AnyObject??。您必须打开它两次才能使用它:

var optional = [String: AnyObject?]()

// I changed it to NSString because String isn't an AnyObject
                            v
optional["controlkey"] = NSString(string: "valueoptional")

print(optional["controlkey"])    // prints "Optional(Optional(valueoptional))"
if let val = optional["controlkey"] {
    print(val)                   // prints "Optional(valueoptional)"
    if let unwrappedVal = val {
        print(unwrappedVal)      // prints "valueoptional"
    }
}