swift - 在 swift4.1 中将 Any 转换为 Float 总是失败

标签 swift downcast swift4.1

在以前的版本中,要从 [String: Any] 字典中获取浮点值,我可以使用 let float = dict["somekey"] as? float,但是在swift4.1中,是不行的。似乎 dict["somekey"] 的类型在我得到它之前被隐式推断为 Double ,所以从 Double 转换为 Float 总是失败。我想知道这是一个新特性还是一个错误。

--这是更新。

我重新下载了一个 Xcode9.2 并做了一些实验,现在我想我弄清楚了是怎么回事。这是测试代码:

let dict: [String : Any] = ["key": 0.1]

if let float: Float = dict["key"] as? Float {
    print(float)
} else {
    print("nil")
}

let dict1: [String : Any] = ["key": NSNumber(value: 0.2)]

if let float: Float = dict1["key"] as? Float {
    print(float)
} else {
    print("nil")
}

let number = NSNumber(value: 0.3)
if let float: Float = number as? Float {
    print(float)
} else {
    print("nil")
}

let number1 = NSNumber(floatLiteral: 0.4)
if let float = number1 as? Float {
    print(float)
} else {
    print("nil")
}

在Swift4和Swift4.1的Playground中运行这段代码,结果是不一样的。在Swift4中,结果是nil 0.2 0.3 0.4,在Swift4.1中结果是 。从结果中,我可以学到两点: 1. 当我们使用JSONSerialization类将JSON数据转换为[String : Any]字典时,数值被保存为一个NSNumber对象,但不是 IntDoubleFloat。 2. 在Swift4中,我们可以使用 let float = NSNumberOjbect as? Float 来获取一个Float 值,但是在Swift4.1 中我们不能。但是,我们仍然可以通过这种方式在 Swift4 或 Swift4.1 中获取 IntDouble 值。 最后再问一次,这是一个新功能还是一个错误?如果有人知道,你们可以显示公告链接吗?

最佳答案

你需要区分两种情况(在 Swift 3 中,是三种情况):

  • Any 包含 Swift 原生 Double
  • 任何 包含一个NSNumber

(在 Swift 3 中,除了正常的 NSNumber 之外还有 type preserving NSNumber case。)


当你创建一个原生的 Swift Dictionary,比如 [String: Any],并以正常的方式设置 Double 值时,就像这样你的更新:

let dict: [String : Any] = ["key": 0.1]

在这种情况下,Any 包含表示 Double 的元数据和原始值 0.1 作为 Double

并且将持有 DoubleAny 转换为 Float 总是失败。 As DoubleFloat 不能用 as 转换。

let dblValue: Double = 0.1
if let fltValue = dblValue as? Float { //<-Cast from 'Double' to unrelated type 'Float' always fails
    print(fltValue)
} else {
    print("Cannot convert to Float")
}
//->Cannot convert to Float

但是,在 Any 持有 NSNumber 的情况下,当 ArrayDictionary 被桥接时总是会发生来自 NSArrayNSDictionary,以前的 Swifts 和 Swift 4.1 之间的行为是不同的。

JSONSerialization 的结果符合这种情况。

在以前的 Swifts 中,(正常的)NSNumberFloat 是一个总是成功的操作。

在 Swift 4.1 中,行为随着我在评论中展示的新功能而改变:

SE-0170 NSNumber bridging and Numeric types


在Swift 3中曾经发现过第三种情况,我省略了,它已经过去了。

但是,如何获取 DictionaryArray 以及如何为它们设置值对于解决 Any 问题非常重要> 到 Float


最后,这是新功能还是错误?如果有人知道,你们可以显示公告链接吗?

这是一项新功能,不是错误。请参阅上面的链接和下面的相关主题。

Unable to bridge NSNumber to Float Swift 3.3

Unexpected behavior when casting an NSNumber to Float

关于swift - 在 swift4.1 中将 Any 转换为 Float 总是失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49607492/

相关文章:

arrays - 如何使 Array<Any> 相等?

json - 可解码和 JSON,同一变量的 2 种数据类型

Xcode 6 代码编辑器不稳定的行为

Swift 代码到类图

C++继承问题

c++ - 为什么 DECLARE_DYNAMIC 和 IMPLEMENT_DYNAMIC 对 DYNAMIC_DOWNCAST 是必要的?

ios - 状态栏找不到缓存的时间字符串图像。正在渲染

swift - 带有 SwiftPM 的 Cocoa 应用程序

ios - 如何从 ios 中的 Skype 应用程序重定向到我的应用程序

cocoa - 在 Swift 中使用 as 和 as 向下转型?