在 Optional Double 上调用方法以转换为 String

Calling a method on an Optional Double to convert to String

我写这篇文章是为了轻松地将浮点数格式化为具有各种精度级别的字符串。

extension FloatingPoint {
    func str(_ precision: Int) -> String {
        return String(format: "%."+String(precision)+"f", self as! CVarArg)
    }
}

它适用于浮点类型的非可选变量:

var myDouble: Double = 3.1415
var text = myDouble.str(2) // sets text = "3.14"

有没有办法让这样的东西用于可选的 Double

var myNilDouble: Double? = nil
var text = myNilDouble.str(2) // I'd like it to set text = "" 

我希望实现支持 nil 和非 nil 到字符串的转换。

您不是在 Double 上调用该方法,您是在 Optional<Double> 上调用它;完全不同的类型。所以你需要方法存在于 Optional:

extension Optional where Wrapped : FloatingPoint {
    func string(usingPrecision precision: Int) -> String {
        guard let double = self else { return "" }
        return double.str(precision)
    }
}

不过我不喜欢这个界面;我认为决定发出空字符串不是 Optional 的工作。相反,我会建议 String 本身采用 Optional 浮点数的初始化程序:

import Foundation

extension String {
    init<N : FloatingPoint>(_ value: N?, precision: Int) {
        guard let value = value else { self.init(); return }
        self.init(format: "%.\(precision)f", value as! CVarArg)
    }
}

现在你写

let value: Double? = nil
let text = String(value, precision: 2)    // ""

另一个选项是免费功能,同样采用 Optional。 (当然,您也可以让调用者选择 nil 解析为什么,正如 Sulthan 所说。)

最简单的解决方案是使用可选链接和零合并:

var text = myNilDouble?.str(2) ?? ""

虽然您最终可能会多次重复此模式,但优点是您可以更好地控制 nil 场景,也许在某些情况下您会希望使用 "(null)" 作为默认值。