ios Swift 将 NSNumber 对象转换为 Double

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27279032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:53:36  来源:igfitidea点击:

Swift convert object that is NSNumber to Double

iosswift

提问by Bryan Cimo

I have this code in Swift and it works, but I would think there is a better way to get my object from NSNumber and convert it to a Double:

我在 Swift 中有这段代码并且它可以工作,但我认为有更好的方法可以从 NSNumber 获取我的对象并将其转换为 Double:

var rating: NSNumber
var ratingDouble: Double

rating = self.prodResult?.prodsInfo.prodList[indexPath.row].avgRating as NSNumber!!

ratingDouble = Double(rating.doubleValue)

回答by Brian Nickel

Update

更新

Swift's behavior here has changed quite a bit since 1.0. Not that it was that easy before, but Swift has made it harder to convert between number types because it wants you to be explicit about what to do with precision loss. Your new choices now look like this:

自 1.0 以来,Swift 在此处的行为发生了很大变化。以前并不是那么容易,但是 Swift 使数字类型之间的转换变得更加困难,因为它希望您明确说明如何处理精度损失。您的新选择现在如下所示:

var rating: NSNumber
var ratingDouble: Double

ratingDouble = rating as! Double // 1
ratingDouble = Double(exactly: rating)! // 2

ratingDouble = Double(truncating: rating) // 3
ratingDouble = rating.doubleValue // 4

if let x = rating as? Double { // 5
    ratingDouble = x
}

if let x = Double(exactly: rating) { // 6
    ratingDouble = x
}
  1. This calls Double._forceBridgeFromObjectiveCwhich calls Double(exactly:)with Double, Int64, or UInt64based on the stored type in rating. It will fail and crash the app if the number isn't exactly representable as a Double. E.g. UInt64.maxhas more digits than Doublecan store, so it'll crash.

  2. This is exactly the same as 1 except that it may also crash on NaNsince that check isn't included.

  3. This function always returns a Doublebut will lose precision in cases where 1 and 2 would crash. This literally just calls doubleValuewhen passing in an NSNumber.

  4. Same as 3.

  5. This is like 1 except that instead of crashing the app, it'll return nil and the inside of the statement won't be evaluated.

  6. Same as 5, but like 2 will return nil if the value is NaN.

  1. 这就要求Double._forceBridgeFromObjectiveC它调用Double(exactly:)DoubleInt64UInt64基于存储的类型rating。如果数字不能完全表示为Double. 例如UInt64.max,数字比Double可以存储的多,所以它会崩溃。

  2. 这与 1 完全相同,只是它也可能崩溃,NaN因为不包括该检查。

  3. 这个函数总是返回 aDouble但在 1 和 2 崩溃的情况下会失去精度。 这实际上只是doubleValue在传入NSNumber.

  4. 与 3 相同。

  5. 这与 1 类似,只是它不会使应用程序崩溃,而是返回 nil 并且不会评估语句的内部。

  6. 与 5 相同,但如果值为 ,则 2 将返回 nil NaN

If you know your data source is dealing in doubles, 1-4 will probably all serve you about the same. 3 and 4 would be my first choices though.

如果您知道您的数据源正在处理双打,那么 1-4 可能都会为您提供相同的服务。3 和 4 将是我的第一选择。



Old Answer for Swift 1 and 2

Swift 1 和 2 的旧答案

There are several things you can do:

您可以执行以下几项操作:

var rating: NSNumber
var ratingDouble: Double

ratingDouble = rating as Double   // 1
ratingDouble = Double(rating)     // 2
ratingDouble = rating.doubleValue // 3
  1. The first item takes advantage of Objective-Cbridging which allows AnyObjectand NSNumberto be cast as Double|Float|Int|UInt|Bool.
  2. The second item presumably goes through a constructor with the signature init(_ number: NSNumber). I couldn't find it in the module or docs but passing AnyObjectin generated an error that it cannot be implicitly downcast to NSNumberso it must be there and not just bridging.
  3. The third item doesn't employ language features in the same way. It just takes advantage of the fact that doubleValuereturns a Double.
  1. 第一项利用了Objective-C桥接的优势,它允许AnyObject并被NSNumber强制转换为Double|Float|Int|UInt|Bool.
  2. 第二项大概通过带有签名的构造函数init(_ number: NSNumber)。我在模块或文档中找不到它,但传入AnyObject产生了一个错误,它不能被隐式向下转换,NSNumber所以它必须在那里而不仅仅是桥接。
  3. 第三项不以同样的方式使用语言特征。它只是利用了doubleValue返回 a的事实Double

One benefit of 1 is that it also works for AnyObjectso your code could be:

1 的一个好处是它也适用,AnyObject因此您的代码可以是:

let ratingDouble = self.prodResult!.prodsInfo.prodList[indexPath.row].avgRating! as Double

Note that I removed the ?from your function and moved the !in. Whenever you use ! you are eschewing the safety of ?so there's no reason to do both together.

请注意,我?从您的函数中删除了并将其移入!。每当您使用 ! 你在回避安全,?所以没有理由一起做。