怪异的Swift 4型系统

iiF*_*man 1 json types ios swift4 xcode9

有人可以解释找出Int类型的最佳方法,因为Swift 4因为这个原因我有很多麻烦

在此输入图像描述

因为当我尝试将相同的json对象映射到核心数据实体和PONSO时,这是很常见的情况

所以,

id: Int = json["id"] as? Int // works
id: Int32 = json["id"] as? Int32 // doesn't work
Run Code Online (Sandbox Code Playgroud)

结果我无法同时满足这两个要求.我能不能在Swift 4中避免这种绝对无意义的int情况?

Cha*_*tka 5

这是令人困惑的原因是因为as?在Swift中有两个完全正交的含义,具体取决于上下文.纯粹使用Swift类型进行处理时,as?是一个动态强制转换,nil只有在类型实际上是as?运算符右侧类型的实例时才返回:

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)
Run Code Online (Sandbox Code Playgroud)

这将返回Optional(3)第一个日志,而返回nil另外两个,因为类型是a Int而不是an Int32或an Int64.

但是,当正在投射的项目的类型是Objective-C类型时,则as?不再是严格的动态强制转换,而是导致桥接行为:

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)
Run Code Online (Sandbox Code Playgroud)

这将返回Optional(3)所有三个日志,因为这不再是动态转换 - 实际上,NSNumber实例不是我们尝试转换的三种类型中的任何一种的成员.相反,如果可以的话,as?导致Swift 将Objective-C类型NSNumber接到适当的Swift类型.由于雨燕具有逻辑桥接NSNumberInt,Int32Int64(与主机的数字类型的一起),我们得到Optional(3)了所有三个日志.但是,如果你试图转换Decimal为没有NSNumber桥接逻辑的东西,你仍然会得到nil.

一个有趣的副作用是as?不遵循传递属性:

let foo: Int = 3
print(foo as? NSNumber as? Int64) // Optional(3)
print(foo as? Int64)              // nil
Run Code Online (Sandbox Code Playgroud)

无论如何,如果你将值转换为NSNumber第一个,那么你应该能够从那里转换为Objective-C桥支持的任何数值类型,这可能是你用旧的Swift 3代码引起的.或者,如果您确实知道该值应该是的类型,则可以使用其他整数类型的初始化器之一:

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

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