Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - setting dictionary value to nil confusion

I'm quite confused:

Let's create a dictionary:

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

Now if I want to remove the key "foo", I can just do

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

And other option could be:

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

But this behaves differently:

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

Similarly to the above (which I think is the same):

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

What is going on? And btw, why does swift let us delete keys with setting them to nil, instead sticking with

d.removeValue(forKey: "foo")

?

like image 285
Guig Avatar asked Sep 22 '16 04:09

Guig


1 Answers

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

This is a sentence from the documentation, so as you can see it is by design. If this not fit your needs then you are doomed to use updateValue(value: Value, forKey: Hashable) which also works more predictable.

What I found is that when you use NSMutableDictionary instead of Dictionary then it works as "expected"

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

However let x = Any? = nil case seems that there is a bug in Swift implementation at least to version Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1)

Btw. when all elements from Dictionary are removed, type of Dictionary is still correctly recognised

let x: String? = nil
d["foo"] = x // d is now [:]
let m = Mirror(reflecting: d) // Mirror for Dictionary<String, Optional<Any>>

I allowed myself to add bug to Swift lang: https://bugs.swift.org/browse/SR-3286

like image 156
sliwinski.lukas Avatar answered Nov 16 '22 03:11

sliwinski.lukas