Swift: `["one": nil] as [String: Any]` 有效,为什么?

Tpo*_*6oH 2 nullable ios swift

func logEvent(events: [String: Any]) {
  print(events);
}

let eventProperties: [String: Any?] = [
  "one": nil,
  "two": "2"
]

logEvent(events: eventProperties as [String: Any])
Run Code Online (Sandbox Code Playgroud)

如果我更改let eventProperties: [String: Any?]为,let eventProperties: [String: Any]我会得到有意义的错误。但为什么上面的代码有效呢?

'nil' is not compatible with expected dictionary value type 'Any'
  "one": nil,
Run Code Online (Sandbox Code Playgroud)

Rob*_*ier 5

每个类型都是 的子类型Any。这包括各种Optional包括Optional<Any>。所以你绝对可以转换[String: Any?][String: Any]because Any?is a kind of Any.

另一方面,文字nil仅适用于Optional,因此let x: Any = nil无效。Any不是Optional

这种混乱是您应该避免Any并且应该强烈避免的一个关键原因Any?。当与可选提升(类型在分配时可以提升为其自身的可选类型这一事实)结合使用时,任何类型很快就会变成一堆令人困惑的错误和微妙的行为。一个非常常见的问题是最终得到Any??像 之类的值.some(nil),它本身并不是零。如果可能的话,请避免这种情况。

对于您的日志记录问题,[String: Any]可能没问题。我自己用过,非常有效。但不要创建[String: Any?]字典。如果你确实需要一个可以包含的 nil 占位符,那么可以这样做:

let anyNil = Any?.none as Any 

let eventProperties: [String: Any] = [
    "one": anyNil,
    "two": "2"
]
Run Code Online (Sandbox Code Playgroud)

(但如果可以的话,我仍然会避免这种情况。)