如何编写处理可选值的字典扩展
Posted
技术标签:
【中文标题】如何编写处理可选值的字典扩展【英文标题】:How to write Dictionary extension that handles optional values 【发布时间】:2015-01-03 16:22:22 【问题描述】:我正在尝试实现Dictionary
扩展,并且我想处理可选值。但无论我做什么,如果我在 [String: String?]
字典上使用我的方法,它就无法选择性地绑定该值。你如何为一个优雅地处理可选值的字典编写一个扩展?
考虑以下扩展:
extension Dictionary
func someMethod()
for (key, value) in self
if let valueString = value as? String
println(" \(key) = \(valueString)")
else
println(" \(key) = \(value) cannot be cast to `String`")
所以考虑下面的代码:
let dictionary: [String: AnyObject?] = ["foo": "bar"]
dictionary.someMethod()
它奇怪地报告
foo = Optional(bar) cannot be cast to `String`
我可以编写一个非扩展方法来处理具有可选值的字典参数,但不知道如何将其作为Dictionary
的扩展。
【问题讨论】:
我可以解释为什么它不像你预期的那样工作。当应用于 Optional 时,as
、is
、as?
和 ==
(以及其他比较器)具有特殊含义:它们应用于事物包装。 if let valueString = value as? String
没有按照您的预期执行的原因是,在编译时我们不知道 value
是 一个 Optional,因此我们不使用特殊含义as
应用于 Optional。我们尝试将 Optional itself 转换为 String,当然失败了;你不能将 Optional itself 投射到任何东西上。
正如您自己所说,我相信,Swift 似乎邀请使用实例方法,但实际的力量在于***全局函数,因为它们允许您构建一个通用约束,只允许通过网格的正确类型,因为它是。字典是泛型的,你不能给泛型添加更多的约束,所以你永远不能用扩展中的实例方法来做到这一点。
【参考方案1】:
你可以通过反射来做到这一点。不需要比现有更多的代码:
extension Dictionary
func someMethod()
for (key, value) in self
var valueRef = _reflect(value)
while valueRef.disposition == .Optional && valueRef.count > 0 && valueRef[0].0 == "Some"
valueRef = valueRef[0].1
if let valueString: String = valueRef.value as? String
print(" \(key) = \(valueString)")
else
print(" \(key) = \(value) cannot be cast to `String`")
let dictionary: [String : AnyObject?] = ["foo" : "bar"]
dictionary.someMethod()
返回
foo = bar
let dictionary: [String : AnyObject?] = ["foo" : nil]
dictionary.someMethod()
返回
foo = nil cannot be cast to `String`
let dictionary: [String : AnyObject?] = ["foo" : UIViewController()]
dictionary.someMethod()
返回
foo = Optional(<UIViewController: 0x7fee7e819870>) cannot be cast to `String`
【讨论】:
【参考方案2】:当我插入 ':String?' 时我没有遇到任何问题valueString 之后如下图:
extension Dictionary
func someMethod() -> Bool
for (key, value) in self
if let valueString:String? = value as? String
println(" \(key) = \(valueString)")
else
println(" \(key) = \(value) cannot be cast to `String`")
return false
return true
func doSomething()
let dictionary: [String: AnyObject?] = ["foo": "bar"]
if dictionary.someMethod()
println("no problems")
else
println("casting issues")
【讨论】:
有趣。当我这样做时,它不会失败并落入“无法转换”(即它返回true
,但valueString
始终是nil
,即使提供了一个值。以上是关于如何编写处理可选值的字典扩展的主要内容,如果未能解决你的问题,请参考以下文章