这是一个最佳实践问题,我感觉我错过了一个明显的解决方案...
我很难过,为什么当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 }
这告诉我它总是如此?
我想我在这里缺少一些关键...所以在这些情况下你们都做了什么?
答案 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)
如果您只想检查一个密钥是否存在,那么"类型转换"到Int
或Double
无关紧要。
为什么不简单
guard c.data["I1"] == nil && !wantsGroundAlways else { return }
如果I1
不在字典中且wantsGroundAlways
为false
,则会通过测试。
if let
或guard let
,因为根据条件,从不使用key的值。