Swift - 将字典值设置为nil混淆

时间:2016-09-22 04:32:53

标签: swift dictionary

我很困惑:

让我们创建一个词典:

var d = ["foo": nil] as [String: Any?]

现在,如果我想删除密钥"foo",我可以

d["foo"] = nil // d is now [:]

其他选择可能是:

let x: String? = nil
d["foo"] = x // d is now [:]

但这种行为有所不同:

let x: Any? = nil
d["foo"] = x // d is still ["foo": nil]

与上述类似(我认为是相同的):

d["foo"] = d["foo"] // d is still ["foo": nil]

发生了什么事?顺便说一句,为什么swift让我们删除键,将它们设置为nil,而不是坚持

d.removeValue(forKey: "foo")

3 个答案:

答案 0 :(得分:3)

/// If you assign `nil` as the value for the given key, the dictionary
/// removes that key and its associated value.

这是文档中的一句话,因为您可以看到它是设计的。如果这不符合您的需求,那么您注定要使用updateValue(value: Value, forKey: Hashable),这也更有效。

我发现,当您使用NSMutableDictionary代替Dictionary时,它的工作原理为"预期"

let ns = NSMutableDictionary(dictionary: d)
let x: Any? = nil
ns["foo"] = x // ns {}

然而,let x = Any? = nil似乎在Swift实现中存在一个错误,至少是版本Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1)

顺便说一下。删除Dictionary中的所有元素后,type的{​​{1}}仍然可以正确识别

Dictionary

我允许自己为Swift lang添加bug:https://bugs.swift.org/browse/SR-3286

答案 1 :(得分:1)

要删除类型为[A: B]的字典中的键,您需要将其值设置为值为B?

nil类型的元素

例如:

var d = ["foo": 1] as [String: Int]
let v: Int? = nil
d["foo"] = v // d is now [:]

或只是

d["foo"] = nil // here nil is casted to Int?

所以,如果我们现在有

var d = ["foo": nil] as [String: Any?]

A = StringB = Any?

要删除与foo相关联的键/值,我们需要将值设置为值B?的{​​{1}} = Any??类型:

nil

当我们做什么时会发生什么

let v: Any?? = nil
d["foo"] = v // d is now [:]

此处d["foo"] = nil 已投放到nil而非Any??,因此它与实际不同

Any?

这就是结果不同的原因。

感谢@sliwinski与苹果公开讨论,将我们与https://developer.apple.com/swift/blog/?id=12

联系起来

答案 2 :(得分:0)

给出这样的字典:

dict: [String: String?] = []

如果您像这样添加nil值:

dict["a"] = nil

字典将为空。但是,如果您像这样添加一个nil值:

dict["a"] = nil as String?

字典将为空。试试吧...

func testDictionary() {
    var dict: [String: String?] = [:]

    dict["abc"] = nil
    print("dictionary is empty -> \(dict.isEmpty)") // -> true

    dict["abc"] = nil as String?
    print("dictionary is empty -> \(dict.isEmpty)") // -> false
}

这似乎很奇怪,而且有细微的差别。有人可以解释吗?