【问题标题】:Left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never usednil 合并运算符 '??' 的左侧具有非可选类型“字符串”,因此从不使用右侧
【发布时间】:2018-10-04 07:24:22
【问题描述】:

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

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

【问题讨论】:

    标签: ios swift optional forced-unwrapping


    【解决方案1】:

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

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

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

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

    如果model.pointsCategory 不为零,则将self.legend 设置为model.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)
    }
    

    【讨论】:

    • @Erent 那么你知道??现在实际上做了什么吗?
    • @Sweeper 为什么此代码有效:- var demoOptinal :String? demoOptinal = "AB" ?? “乙”
    • @Amey 它没有。它会产生警告。
    • 哦,没看到谢谢
    【解决方案2】:

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

    【讨论】:

    • .name 属性是来自目标 c 类的属性。在这个项目中,我正在与 OC 和 swift 一起工作。因此我无法将属性更改为可选
    • 当我尝试添加括号时,我仍然收到此错误:nil 合并运算符的左侧 '??'具有非可选类型“字符串”,因此从不使用右侧
    • 如果你有一个Objective-C属性被声明为nonnull,但同时又能返回nil,那你就麻烦了。
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 所以基本上这段代码永远不会工作?让 formattedPointsValue: String? self.formattedPointsValue = model.pointUnitsEarned.stringValueWithWhiteSpaceThousandSeperator()+" "+"model.name".localized(in: .name) ?? .无
    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 2013-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2016-06-08
      • 2022-12-05
      相关资源
      最近更新 更多