我通过api json响应(我将其转换为[String: Any]
字典)接收一组整数.这些整数保证在10 ... -10(包括)范围内.在我的模型中,我想将它们存储为Int8
.
这就是我将我的json字典转换为它的模型对象的方法,但我想知道是否有一种更惯用的方法来确保json中的int实际上适合于Int8
?
func move(with dict: JSONDictionary) -> Move? {
if let rowOffset = dict[JSONKeys.rowOffsetKey] as? Int,
let colOffset = dict[JSONKeys.colOffsetKey] as? Int {
if let rowInt8 = Int8(exactly: rowOffset),
let colInt8 = Int8(exactly: colOffset) {
return Move(rowOffset: rowInt8, colOffset: colInt8)
}
else {
print("Error: values out of range: (row: \(rowOffset), col: \(colOffset)")
}
} else {
print("Error: Missing key, either: \(JSONKeys.rowOffsetKey) or \(JSONKeys.colOffsetKey)")
}
return nil
}
请注意,无论传入的int值如何,执行以下操作始终会失败:
if let rowOffset = dict[JSONKeys.rowOffsetKey] as? Int8,
let colOffset = dict[JSONKeys.colOffsetKey] as? Int8 {
...
这就是我将传入的json转换为字典的方式.有问题的json是深层嵌套的,包含几种不同的类型.
typealias JSOnDictionary= [String: Any]
let jsOnDict= try JSONSerialization.jsonObject(with: data) as? JSONDictionary
vacawama..
9
以下是将您的Int
(来自a NSNumber
)转换为以下内容的一些选项Int8
:
只需转换为Int8
初始化程序init(_: Int)
如果您的Int
值保证适合a Int8
,那么转换它们Int8(value)
很好.
如果你得到一个Int
不适合的Int8
,你的程序将崩溃:
let i = 300
let j = Int8(i) // crash!
用Int8
初始化器初始化init(truncatingIfNeeded: BinaryInteger)
为了更加安全,您应该使用init(truncatingIfNeeded: BinaryInteger)
初始化程序:
let i = 300
let j = Int8(truncatingIfNeeded: i) // j = 44
这确实产生了可能不合需要的改变值,但它可以防止崩溃.
明确检查有效值的范围
作为另一种选择,您可以明确检查范围:
if (-10...10).contains(i) {
j = Int8(i)
} else {
// do something with the error case
}
检查的优点是您可以指定有效范围,而不是仅在范围超出适合的值时检测错误Int8
.
用Int8
初始化器初始化init(exactly: Int)
您的代码当前正在使用这种安全初始化Int8
值的方法.这是健壮的,因为nil
如果值不适合,它将返回Int8
.因此,它可以使用可选绑定进行检查,或者可以与nil合并运算符组合 ??
以提供默认值(如果您有适当的值):
// Determine Int8 value, use 0 if value would overflow an Int8
let j = Int8(exactly: i) ?? 0
在Swift 3.0.1及更高版本中直接NSNumber
使用as Int8
正如@Hamish和@OOPer在评论中提到的,现在可以NSNumber
直接投射到Int8
.
let i: NSNumber = 300
let j = i as Int8 // j = 44
这确实具有与使用相同的截断效果init(truncatingIfNeeded: BinaryInteger)
.
总之,您当前的代码是安全的,并且可能是您问题的最佳解决方案,除非您想要检测值何时超过当前所需的范围-10...10
,在这种情况下,显式检查将是更好的选择.
1> vacawama..:
以下是将您的Int
(来自a NSNumber
)转换为以下内容的一些选项Int8
:
只需转换为Int8
初始化程序init(_: Int)
如果您的Int
值保证适合a Int8
,那么转换它们Int8(value)
很好.
如果你得到一个Int
不适合的Int8
,你的程序将崩溃:
let i = 300
let j = Int8(i) // crash!
用Int8
初始化器初始化init(truncatingIfNeeded: BinaryInteger)
为了更加安全,您应该使用init(truncatingIfNeeded: BinaryInteger)
初始化程序:
let i = 300
let j = Int8(truncatingIfNeeded: i) // j = 44
这确实产生了可能不合需要的改变值,但它可以防止崩溃.
明确检查有效值的范围
作为另一种选择,您可以明确检查范围:
if (-10...10).contains(i) {
j = Int8(i)
} else {
// do something with the error case
}
检查的优点是您可以指定有效范围,而不是仅在范围超出适合的值时检测错误Int8
.
用Int8
初始化器初始化init(exactly: Int)
您的代码当前正在使用这种安全初始化Int8
值的方法.这是健壮的,因为nil
如果值不适合,它将返回Int8
.因此,它可以使用可选绑定进行检查,或者可以与nil合并运算符组合 ??
以提供默认值(如果您有适当的值):
// Determine Int8 value, use 0 if value would overflow an Int8
let j = Int8(exactly: i) ?? 0
在Swift 3.0.1及更高版本中直接NSNumber
使用as Int8
正如@Hamish和@OOPer在评论中提到的,现在可以NSNumber
直接投射到Int8
.
let i: NSNumber = 300
let j = i as Int8 // j = 44
这确实具有与使用相同的截断效果init(truncatingIfNeeded: BinaryInteger)
.
总之,您当前的代码是安全的,并且可能是您问题的最佳解决方案,除非您想要检测值何时超过当前所需的范围-10...10
,在这种情况下,显式检查将是更好的选择.
我更新了我的答案.它包含了评论中的信息.