从可选容器中提取非可选值的最佳方法

时间:2016-06-22 15:18:41

标签: swift

这是一个最佳实践问题,我感觉我错过了一个明显的解决方案...

我很难过,为什么当wantsGroundAlways为假且I1未定义时,这段代码使其超过if:

let i = c.data["I1"]?.integerValue
if !wantsGroundAlways && i == 0 { return }

问题在于data["I1"]根据定义是可选的,因此Swift将i推断为int?,并且nil!= 0.微妙,但回想起来很明显。

处理这种常见情况的最佳方式?一个解决方案是:

let i = (c.data["I1"] ?? 0).integerValue

但我个人认为这看起来很糟糕并隐藏了意图。有点像:

guard let i = c.data["I1"]?.integerValue else { i = 0 }

会明确显示您尝试做的事情,但它无法正常工作,因为我无法在else子句中访问i而且{ let i = 0 }不一样i (试试吧,你会明白我的意思)。

现在有这个:

guard let arcradius = c.data["F1"]?.doubleValue else { return }

似乎真的接近我想做的事情,但我不确定这是否真的是我认为的意思 - 如果F1不在dict中,那么返回真的会被激活?这个版本与此之间的区别是什么:

guard case let arcradius = c.data["F1"]?.doubleValue else { return }

这告诉我它总是如此?

我想我在这里缺少一些关键...所以在这些情况下你们都做了什么?

2 个答案:

答案 0 :(得分:3)

我认为这是解决第一个问题最直接,最富有表现力的方式:

let i = c.data["I1"]?.integerValue ?? 0

它不需要括号,并显示意图。

?? nil coalescence运算符。它是一个二元运算符。如果左操作数不是nil,则返回它,否则返回右操作数。

c.data["I1"]可以是nil(因为"I1"密钥可能没有值)。在这种情况下,c.data["I1"]?.integerValue将为nil??将返回0。如果一切顺利,左侧不是nil,则会返回,忽略0

答案 1 :(得分:1)

如果您只想检查一个密钥是否存在,那么"类型转换"到IntDouble无关紧要。

为什么不简单

guard c.data["I1"] == nil && !wantsGroundAlways else { return }

如果I1不在字典中且wantsGroundAlwaysfalse,则会通过测试。

不需要

if letguard let,因为根据条件,从不使用key的值。