4

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

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

但是我收到警告

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

当我删除?? .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

4 回答 4

4

??我认为您对运营商有些困惑。

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

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

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

设置self.legendmodel.pointsCategoryifmodel.pointsCategory不为零。如果为 nil,则设置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)
}
于 2018-04-24T06:51:14.230 回答
0

.name 属性不是可选的,这就是为什么出现错误的原因使 .name 属性在模型中是可选的

于 2018-04-24T06:31:04.080 回答
0

??只有当左边的值可以是时才有用nil

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

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

nil 合并运算符的要点是,如果值不存在,则能够回退到默认值,如果始终存在值,则使用它毫无意义,这就是您收到警告的原因。

于 2018-04-24T06:39:57.027 回答
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)"

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

于 2020-05-20T07:22:27.103 回答