简体   繁体   English

怪异的Swift 4型系统

[英]Weird Swift 4 type system

Can someone explain the best best way to figure out Int types, since Swift 4 I have so many troubles with JSON because of this 有人可以解释找出Int类型的最佳方法吗,因为Swift 4由于这个原因,我在JSON方面遇到了很多麻烦

在此处输入图片说明

cause this is so common situation when I trying to map same json object to core data entities and PONSOs 当我尝试将相同的json对象映射到核心数据实体和PONSO时,这是很常见的情况

so, 所以,

id: Int = json["id"] as? Int // works
id: Int32 = json["id"] as? Int32 // doesn't work

as a result I'm unable to satisfy both requirements at the same time. 结果,我无法同时满足这两个要求。 Can I anyhow avoid this absolutely senseless int situation in Swift 4? 我能以某种方式避免Swift 4中这种绝对毫无意义的int情况吗?

The reason this is confusing is because as? 造成混淆的原因是因为as? has two completely orthogonal meanings in Swift, depending on the context. 根据上下文,在Swift中有两个完全正交的含义。 When dealing purely with Swift types, as? 当纯粹处理Swift类型时, as? is a dynamic cast that returns non- nil only if the type is literally an instance of the type on the right-side of the as? 是仅当类型从字面上是as?右侧类型的实例时才返回nil的动态转换as? operator: 操作员:

import Foundation

let dict: [String : Any] = ["Foo" : 3 as Int]

print(dict["Foo"] as? Int)
print(dict["Foo"] as? Int32)
print(dict["Foo"] as? Int64)

This returns Optional(3) for the first log, and nil for the other two, because the type is an Int and not an Int32 or an Int64 . 这将为第一个日志返回Optional(3) ,为其他两个日志返回nil ,因为类型是Int而不是Int32Int64

However, when the type of the item being cast is an Objective-C type, then as? 但是,当要投射的项的类型为Objective-C类型时,该as? is no longer a strict dynamic cast, but instead causes bridging behavior: 不再是严格的动态转换,而是导致桥接行为:

import Foundation

let dict: [String : Any] = ["Foo" : 3 as NSNumber]

print(dict["Foo"] as? Int)
print(dict["Foo"] as? Int32)
print(dict["Foo"] as? Int64)

This returns Optional(3) for all three logs, because this is no longer a dynamic cast—indeed, an NSNumber instance is not a member of any of the three types to which we tried to cast. 这将为所有三个日志返回Optional(3) ,因为它不再是动态强制转换-实际上, NSNumber实例不是我们尝试强制转换为这三种类型中任何一种的成员。 Instead, as? 相反, as? causes Swift to bridge the Objective-C type, NSNumber , to an appropriate Swift type if it can. 使Swift可以将Objective-C类型NSNumber 接到适当的Swift类型。 Since Swift has logic to bridge NSNumber to Int , Int32 , and Int64 (along with a host of other numeric types), we get Optional(3) for all three logs. 由于Swift具有将NSNumber桥接到IntInt32Int64 (以及许多其他数字类型)的逻辑,因此对于所有三个日志,我们都获得Optional(3) However, if you try to cast to something like Decimal for which there's no NSNumber bridging logic, you still get nil . 但是,如果您尝试DecimalDecimal ,而没有NSNumber桥接逻辑,则仍然会得到nil

An interesting side-effect of this is that as? 有趣的副作用是as? does not follow the transitive property: 不遵循传递属性:

let foo: Int = 3
print(foo as? NSNumber as? Int64) // Optional(3)
print(foo as? Int64)              // nil

Anyway, if you cast your values to NSNumber first, you should then be able to cast from there to any of the numeric types that the Objective-C bridge supports, which is probably what was going on under the hood with your old Swift 3 code. 无论如何,如果您首先将值转换为NSNumber ,则应该能够从那里转换为Objective-C桥支持的任何数字类型,这很可能就是您旧的Swift 3代码的幕后故事。 。 Alternatively, if you actually know the type that the value is supposed to be, you can use one of the other integer types' initializers: 另外,如果您实际上知道该值应为的类型,则可以使用其他整数类型的初始化程序之一:

let dict: [String : Any] = ["Foo" : 3 as Int]

let foo = (dict["Foo"] as? Int).map { Int32($0) }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM