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

Left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used

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

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

但是我收到了警告

Left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used.

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

fatal error: unexpectedly found nil while unwrapping an Optional value

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

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

.name 属性 不是可选的,这就是错误出现的原因 make .name 属性 optional in model

??只有在左边的值可以是nil

时才有用

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

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

nil 合并运算符的要点是能够在值不存在时回退到默认值,如果总是有值,则使用它没有意义,所以这就是为什么你'正在收到警告。

我认为您对 ?? 运算符有点困惑。

你认为这行得通是因为 legend 是可选的,不是吗?

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

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

set self.legend to model.pointsCategory if model.pointsCategory is not nil. If it is nil, set self.legend to .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)
}

model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name)==> 应该 return 可选字符串的值

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

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)"

所以结论是合并运算符'??'将从右到左替换或使用默认值。不是从左到右。