在swift4.1中将Any强制转换为Float总是失败 [英] Cast Any to Float always fails in swift4.1

查看:422
本文介绍了在swift4.1中将Any强制转换为Float总是失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In the former version, to get a float value from a [String: Any] dictionary, I can use let float = dict["somekey"] as? Float, but in swift4.1, it doesn't work. It seems the type of dict["somekey"] has been implicitly inferred as Double before I get it, so casting from Double to Float always fails. I wonder if it is a new characteristic or just a bug.

-这是更新.

我重新下载了Xcode9.2,并做了一些实验,现在我想我知道发生了什么.这是测试代码:

I re-downloadeded an Xcode9.2 and did some experiments, now I think I figure out what's going on. Here is the test code:

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中,结果为nil nil nil nil.从结果中,我可以学到两点: 1.当我们使用JSONSerialization类将JSON数据转换为[String : Any] dictionary时,数值将保存为NSNumber对象,但不保存为IntDoubleFloat. 2.在Swift4中,我们可以使用let float = NSNumberOjbect as? Float来获取Float值,但是在Swift4.1中则不能.但是,仍然可以通过这种方式在Swift4或Swift4.1中获得IntDouble值. 最后,这是一个新功能还是一个错误?如果有人知道,你们可以显示公告链接吗?

Running this code in Playground of Swift4 and Swift4.1, the results are different. In Swift4, the results are nil 0.2 0.3 0.4, and In Swift4.1 the results are nil nil nil nil. From the result, I can learn two points: 1. When we convert JSON data into a [String : Any] dictionary with the JSONSerialization class, the numeric value is saved as an NSNumber object, but not Int, Double or Float. 2. In Swift4, we can use let float = NSNumberOjbect as? Float to get a Float value, but in Swift4.1 we can't. But still, we can get Int or Double value in this way, either in Swift4 or Swift4.1. Finally again, is this a new feature or a bug? If someone knows, can you guys show up the announcement link?

推荐答案

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

You need to distinguish two cases (in Swift 3, it was three cases):

  • Any包含Swift本机Double
  • Any包含NSNumber
  • Any containing a Swift native Double
  • Any containing an NSNumber

(在Swift 3中,存在

(In Swift 3, there was type preserving NSNumber case other than the normal NSNumber.)

创建诸如[String: Any]之类的本机Swift Dictionary时,在更新中以常规方式设置Double值:

When you create a native Swift Dictionary such as [String: Any], and set Double value in a normal way like this in your update:

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

在这种情况下,Any将表示Double的元数据和原始值0.1保留为Double.

In this case, Any holds the metadata representing Double and the raw value 0.1 as Double.

并且将Double保持为Float的强制转换Any总是失败.由于DoubleFloat不能用as -castings转换.

And casting Any holding Double to Float always fails. As Double to Float cannot be converted with as-castings.

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的情况下,就像从NSArrayNSDictionary桥接ArrayDictionary时一样,在以前的Swifts和Swift 4.1之间,行为是不同的.


But, in case of Any holding NSNumber, as always happens when the Array or Dictionary is bridged from NSArray or NSDictionary, the behaviors are different between former Swifts and Swift 4.1.

JSONSerialization的结果与此情况匹配.

The result of JSONSerialization matches this case.

在以前的Swift中,(正常)从NSNumberFloat是总是成功的操作.

In former Swifts, (normal) NSNumber to Float was an always-success operation.

在Swift 4.1中,行为随着我在注释中显示的新功能而改变:

And in Swift 4.1, the behavior has changed with the new feature which I have shown in my comment:

SE-0170 NSNumber桥接和数字类型

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

I omit the third case once found in Swift 3, it's past.

但是,非常重要的是如何获取DictionaryArray以及如何为其设置值,以解决AnyFloat的问题.

But it is very important how you get your Dictionary or Array, and how you set the value to them, to solve the issue Any to Float.

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

Finally again, is this a new feature or a bug? If someone knows, can you guys show up the announcement link?

这是一项新功能,而不是错误.请参阅上面的链接,以及下面的相关线程.

This is a new feature, not a bug. See the link above, and related threads below.

无法将NSNumber桥接到Float Swift 3.3

将NSNumber强制转换为Float时的意外行为

这篇关于在swift4.1中将Any强制转换为Float总是失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆