无法将NSNumber转换为Float Swift 3.3

5

在一次Xcode更新后,我遇到了一个奇怪的问题。在我的应用程序中,当我从API获取响应时,我需要手动解析并将其映射到我的模型中。在我的代码中有很多地方都使用了null coalescing将JSON值强制转换为Float,像下面这样:

randomVariable = jsonDict["jsonKey"] as? Float ?? 0

之前它表现正常,但更新后总是默认为0。为了确定原因,我尝试将其强制转换为Float,如下所示:

randomVariable = jsonDict["jsonKey"] as! Float

这导致了以下错误:

无法将NSNumber转换为Float

经过进一步调查,我发现Xcode正在使用Swift 3.3(之前是Swift 3.2)。在StackOverflow上找到的解决方案都是围绕将其强制转换为NSNumber而不是Float。正如我上面提到的,我的应用程序中有类似的代码行分散在各处。我想知道是否有一种方法来解决这个问题。也许可以使用某种扩展?

在Xcode 9.2和Swift 4.0中,将类型强制转换为Float没有问题。 - rmaddy
1
是的,它确实存在。这是Xcode 9.3和Swift 3.3的问题。 - Malik
1
Xcode 9.3 使用 Swift 4.1。 - rmaddy
我知道这个。它也支持Swift 3.3。由于我的代码库是Swift 3,它将其默认为Swift 3.3。 - Malik
3个回答

15

正如您已经发现的那样,您可能需要首先将它转换为NSNumber

可以尝试以下代码:

randomVariable = (jsonDict["jsonKey"] as? NSNumber)?.floatValue ?? 0

或许使用正则表达式替换可以帮助您更新代码。

模式:jsonDict\[([^\]]*)\] as\? Float

替换为:(jsonDict[$1] as? NSNumber)?.floatValue


感谢您的建议。我会接受这个答案,因为它提供了一个解决方案。虽然在我的情况下,这将导致大量的测试,所以我最终还是把我的Xcode回退到了9.2版本。 - Malik
在我的情况下,我没有很多浮点映射,所以我是逐个文件更新而不是整个项目更新。 - Vrutin Rathod

5
问题出在32位架构和Swift 4.1中更新的NSNumber类上。
例如,当我将数字1.1写入字典时,它将被存储为64位NSNumber,其最精确表示为1.10000000000000008881784197001...。因此,当您将其读取为Float时,会失败,因为32位精度不足以获取这个最精确的表示。
32位中最精确的表示为1.10000002384185791015625。
因此,您需要获取在NSNumber.floatValue()函数中实现的截断结果。 浮点数的64位表示
randomVariable = (jsonDict["jsonKey"] as! NSNumber).floatValue

这绝对是我遇到的问题。我已经测试了多个具有不同有效数字的 NSNumber,并且在不同的 Swift 版本中进行了测试。 - InkGolem

0
在我发现 SwiftyJSON 之前,我通常手动解析数据。你可以查看他们的源代码来了解它是如何解析你的数据的。
// Sample: rate is a Float

// Number
if let number = dictionary[SerializationKeys.rate] as? NSNumber {
    print("IS A NUMBER")
    rate = number.floatValue
}

// String

if let string = dictionary[SerializationKeys.rate] as? String {
    print("IS A STRING")
    let decimalNumber = NSDecimalNumber(string: string)
    rate = decimalNumber.floatValue
}

既然我提到了SwiftyJSON,我想推荐它来避免这种头疼。把json解析交给那个家伙吧。https://github.com/SwiftyJSON/SwiftyJSON

希望能有所帮助。


我现在知道SwiftyJSON,但在开始构建这个应用程序时我不知道它。更好的方法是将其更新到Swift 4,因为它有自己的解析器。但无论哪种情况,问题在于代码库很大,更新所有内容需要很长时间。这就是为什么我在寻找一些关于这个问题的见解,以便提出快速修复方案。 - Malik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接