零合并算子的左侧' ??'具有非可选类型' String',因此从不使用右侧

时间:2018-04-24 06:28:51

标签: ios swift optional forced-unwrapping

我有一个以下代码,我试图用来初始化变量并对其执行一些操作。

let formattedPointsValue: String?
self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name) ?? .none

但是我收到了警告

  

零合并算子的左侧' ??'具有非可选类型'字符串'因此从不使用右侧。

当我删除?? .none我的项目运行正常没有问题但是当我运行我的单元测试我得到一个错误

  

致命错误:在解包可选值时意外发现nil

我发现解决此问题的唯一方法是使用此代码。

if let unformattedValue = model.pointUnitsEarned {
    self.formattedPointsValue = unformattedValue.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name)
} else {
    self.formattedPointsValue = nil
}

我想理解为什么这样的事情有效:

let legend: String?
self.legend = model.pointsCategory ?? .none

但这失败了:

let formattedPointsValue: String?
self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name) ?? .none

4 个答案:

答案 0 :(得分:3)

我认为你与??运算符有点混淆。

您认为这有效,因为legend是可选的,不是吗?

let legend: String?
self.legend = model.pointsCategory ?? .none

这不是原因!上述原因的实际原因是因为model.pointsCategory是可选的。它与=左侧的内容无关。这完全是关于??左侧的操作数。所以上面说的是这样的:

  如果self.legend不为零,则

model.pointsCategory设置为model.pointsCategory。如果为零,请将self.legend设置为.none

在这种情况下:

self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+
    " "+"model.name".localized(in: .name) ?? .none

由于"model.name".localized(in: .name)不是可选的,因此无法编译。我怀疑你打算在这里做的是:

if self.formattedPointsValue == nil {
    self.formattedPointsValue = .none
} else {
   self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+
        " "+"model.name".localized(in: .name)
}

答案 1 :(得分:0)

.name属性不是可选的,这就是为什么错误是在模型

中使make .name属性可选

答案 2 :(得分:0)

??仅在左侧的值为nil时才有用,

斯威夫特告诉你,它永远不会是nil所以永远不会使用右边的值。您也可以删除: String?

model.pointsCategory的值是可选的,因此可能是nil,这就是为什么它适用于此并且不会给您任何错误或警告的原因。

如果一个值不存在,那么nil合并运算符的意思是能够回退到一个默认值,如果总有一个值就没有意义使用它,所以这就是你得到的原因一个警告。

答案 3 :(得分:0)

model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+“” +“ model.name” .localized(in:.name)==>应该返回可选字符串的值

例如: 以下代码将收到与您收到的错误相同的

let nickName: String = "k"
let fullName: String? = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"

但是下面的代码可以正常工作。

let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"

因此得出的结论是, Coalescing运算符'??'将替换或使用从右侧到左侧的默认值。不是从左到右。