【问题标题】:Why does NumberFormatter's string(from:) return an optional?为什么 NumberFormatter 的 string(from:) 返回一个可选项?
【发布时间】:2018-01-29 15:24:06
【问题描述】:

Documentation link

为什么NumberFormatter 函数func string(from number: NSNumber) -> String? 返回String? 而不是StringNumberFormatter 是否有特定的输入或状态,该函数可以返回 nil?有时我听说这些不太理想的返回类型来自 Objective-C 保留文件,这是其中一种情况吗?

【问题讨论】:

  • @vadian 谢谢。我想,实际上,我来这里是想问我是否可以在我想要的时候凭良心强行解开这些陈述,而那篇文章让我倾向于“是”。
  • @vadian:其实这是同一个问题。 (虽然答案并不完全令人满意。)
  • @MartinR 这就是我没有将其标记为重复的原因????

标签: ios swift


【解决方案1】:

只是为了好玩:这是一个(构建的,非真实世界的)示例,其中 string(from:)实际上返回nil

let num = NSNumber(bytes: UnsafeRawPointer(bitPattern: 1)!, objCType: "v")
print(num) // <>

let fmt = NumberFormatter()
fmt.numberStyle = .decimal
let str = fmt.string(from: num)

print(str as Any) // nil

原因是这个num不代表数字:它是被创建的 使用NSValue(从它继承)初始化程序 init(bytes:objCType:) 的值表示 void。 ("v" 是type encodingvoid, 指针值无关紧要。)

【讨论】:

  • 你怎么知道这一切的?!不错:)
【解决方案2】:

Apple mailing list 上有一个古老的(2002 年)回复可能会部分回答您的问题:

奇怪的行为不是 NSNumber —— NSNumber -stringValue 似乎返回了人们期望的结果。返回异常结果的是 NSNumberFormatter。

这里的抽象问题是 NSNumberFormatter 最初是为处理 EOF 的金额而编写的,因此它不能很好地处理不寻常的数字(或通用的字符串格式)。

更具体的问题是,当您向 NSNumberFormatter 询问 -stringForObjectValue: 时,如果对象不是 NSDecimalNumber,它会使用以下方法将其转换为 NSDecimalNumber [NSDecimalNumber decimalNumberWithString:[objectValue stringValue]] 除了潜在的其他问题之外,它不会很好地处理异常值。另一个问题,虽然我不知道是这种情况,但我认为没有正负无穷大的 NSDecimal(结构)表示,就像 NaN 那样。

我实际上并没有充分理解该响应,无法说这就是返回可选项的原因,但我怀疑它是相关的。

原始问题中有示例代码,但没有一个返回nil,它总是给出一个字符串。

【讨论】:

  • 最相关的部分似乎是“当您向 NSNumberFormatter 询问 -stringForObjectValue: 时,如果对象不是 NSDecimalNumber,它会使用 [NSDecimalNumber decimalNumberWithString:[objectValue stringValue]] 将其转换为 NSDecimalNumber这不会很好地处理异常值”。听起来好像那里有一个实现细节,可能会导致 Obj-C 用例中的 null 值,而不是 Swift。
  • 感谢您挖掘这个!答案比我预期的要多。
  • 干杯,这是一个有趣的问题。也许一些 Apple 工程师对 NaN 是否应该为 nil 存在争议,他们妥协了一个可选的。 ?‍♂️
【解决方案3】:

我认为公平地说,如果您尝试使用 NumberFormatter 将常见类型(如 Double)格式化为 String,则它不可能返回 nil

在我看来,这是强制解包选项非常有意义的少数情况之一。

func formatToDecimalNumber(_ value: Double) -> String {
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.minimumFractionDigits = 0
    formatter.maximumFractionDigits = 2
    formatter.locale = Locale.current
    return formatter.string(from: NSNumber(value: value))!
}

【讨论】:

  • 为了更加安全,您可以将?? "\(value)" 添加到退货中。取决于格式在您的应用中的重要性。
猜你喜欢
  • 2019-03-10
  • 2020-11-12
  • 2013-02-26
  • 2017-10-04
  • 2020-04-05
  • 2017-03-25
  • 1970-01-01
  • 2016-04-19
  • 1970-01-01
相关资源
最近更新 更多