我在一个操场文件中有以下代码:
extension Dictionary {
func test() {
for key in self.keys {
self[key]
}
}
}
var dict: [String: AnyObject?] = [
"test": nil
]
dict.test()
我今后将把for-each循环中的行称为输出,因为它是相关的。在此特定实例中,输出为nil
。
当我将for-each循环更改为如下所示:
for key in self.keys {
print(self[key])
}
输出为"Optional(nil)\n"
。
我真正想做的是检查nil的值,但是代码:
for key in self.keys {
self[key] == nil
}
输出false
。
我尝试的另一件事是:
for key in self.keys {
self[key] as! AnyObject? == nil
}
产生错误:
Could not cast value of type 'Swift.Optional<Swift.AnyObject>' to 'Swift.AnyObject'
非常感谢任何帮助!
答案 0 :(得分:7)
你已经弄得一团糟了,因为一个值为nil
的词典可以让你看到双包裹的可选的前景,因此有两种{ {1}}。如果密钥丢失,则会获得nil
,如果密钥不,则会获得nil
并解包所获取的结果。不幸的是,你正在一个操场上进行测试,这是一个探索这种区别的糟糕场所。
要明白我的意思,请考虑以下几点:
nil
var d : [String:Int?] = ["Matt":1]
let val = d["Matt"]
的类型是什么?它是val
- 包含在另一个Optional中包含的可选的Int。这是因为根据定义, in 字典中的值是包含在Optional中的Int,然后通过其键获取值包装在 another Optional中。
现在让我们再进一步,这样做:
Int??
什么是var d : [String:Int?] = ["Matt":nil]
let val = d["Matt"]
?好吧,操场可能说它是val
,但事实更复杂;它是nil
包装在另一个可选中。如果你打印 nil
,这是最容易看到的,在这种情况下,你得到的不是val
,而是nil
。
但是如果我们尝试一下根本没有关键的东西,我们会得到一个不同的答案:
"Optional(nil)"
真的是 let val2 = d["Alex"]
,表示密钥丢失了。如果我们打印 nil
,我们会得到val2
。操场未能区分("nil"
和nil
都显示val
,但转换为字符串(val2
所做的)显示差异。
问题的一部分是整个双重包装的可选事物,另一部分是Playground以非常误导的方式表示双重包装的选项。
MORAL 1 :值类型为Optional的字典可能会非常棘手。
道德2 :游乐场是魔鬼的作品。避免他们。使用真实应用程序,并使用日志记录到控制台或调试器的变量窗格,以查看实际发生的情况。
答案 1 :(得分:3)
检查词典值nil
是否有意义
字典值是Optional
类型,这意味着你必须这样做
将您的扩展方法限制为该情况。
这可以通过定义所有可选类型符合的协议来实现 to(比较How can I write a function that will unwrap a generic property in swift assuming it is an optional type?,这只是Creating an extension to filter nils from an Array in Swift的略微修改):
protocol OptionalType {
typealias Wrapped
var asOptional : Wrapped? { get }
}
extension Optional : OptionalType {
var asOptional : Wrapped? {
return self
}
}
现在您可以定义一个限制为的扩展方法 可选值类型的字典:
extension Dictionary where Value : OptionalType {
func test() {
for key in self.keys { ... }
}
}
正如马特已经解释的那样,self[key]
只有nil
才能获得该密钥
在字典中缺少,这不可能发生在这里。那么你
总是可以检索该键的值
let value = self[key]!
在那个循环里面。更好,枚举键和值:
for (key, value) in self { ... }
现在value
是字典值(对于key
)及其类型
符合OptionalType
。使用asOptional
协议属性
你得到一个可选的,可以针对nil进行测试:
if value.asOptional == nil { ... }
或与可选绑定一起使用。
把所有这些放在一起:
extension Dictionary where Value : OptionalType {
func test() {
for (key, value) in self {
if let unwrappedValue = value.asOptional {
print("Unwrapped value for '\(key)' is '\(unwrappedValue)'")
} else {
print("Value for '\(key)' is nil")
}
}
}
}
示例:
var dict: [String: AnyObject?] = [
"foo" : "bar",
"test": nil
]
dict.test()
输出:
Value for 'test' is nil Unwrapped value for 'foo' is 'bar'