Ios 我可以直接将Int64转换为Int吗?
我最近一直在使用SQLite.swift来构建我的应用程序数据库。 我用Ios 我可以直接将Int64转换为Int吗?,ios,swift,sqlite.swift,Ios,Swift,Sqlite.swift,我最近一直在使用SQLite.swift来构建我的应用程序数据库。 我用Int64类型定义了我所有的INTEGER列,就像文档中解释的那样 但是偶尔我需要Int64就是Int。 所以我的问题是,如果我这样做: //Create a table with Int instead of Int64 let test_id = Expression<Int>("test_id") let tests = db["tests"] db.create(table: tests, ifNotE
Int64
类型定义了我所有的INTEGER
列,就像文档中解释的那样
但是偶尔我需要Int64
就是Int
。
所以我的问题是,如果我这样做:
//Create a table with Int instead of Int64
let test_id = Expression<Int>("test_id")
let tests = db["tests"]
db.create(table: tests, ifNotExists: true){ t in
t.column(test_id)
}
class func insertTest(t: Int) -> Int{
//insert.rowid returns an Int64 type
let insert = tests.insert(test_id <- t)
if let rowid = insert.rowid{
//directly cast Int64 into Int
return Int(rowid)
}
return 0
}
//使用Int而不是Int64创建表
让test\u id=表达式(“test\u id”)
let tests=db[“tests”]
create(表:tests,ifNotExists:true){t in
t、 列(测试id)
}
类func insertTest(t:Int)->Int{
//insert.rowid返回Int64类型
让insert=tests.insert(test_id通过将Int64
值传递给Int
初始值设定项,将Int64
转换为Int
,将始终在64位机器上工作,并且如果整数超出范围Int32.min…Int32.max
,它将在32位机器上崩溃
为安全起见,请使用init(truncatingIfNeeded:)
初始值设定项(在早期Swift版本中以前称为init(truncatingBitPattern:)
)转换值:
return Int(truncatingIfNeeded: rowid)
在64位机器上,truncatingIfNeeded
不会起任何作用;您只会得到一个Int
(它的大小与Int64
的大小相同)
在32位计算机上,这将丢弃前32位,但如果它们都是零,则不会丢失任何数据。因此,只要您的值适合32位Int
,您就可以在不丢失数据的情况下执行此操作。如果您的值超出范围Int32.min…Int32.max
,这将更改Int64的值
转换为适合32位Int
的内容,但不会崩溃
您可以看到这在操场中是如何工作的。由于操场中的Int
是64位Int
,因此可以显式使用Int32
来模拟32位系统的行为
let i: Int64 = 12345678901 // value bigger than maximum 32-bit Int
let j = Int32(truncatingIfNeeded: i) // j = -539,222,987
let k = Int32(i) // crash!
Swift 3/4更新
除了仍然有效的init(truncatingIfNeeded:)
之外,Swift 3还引入了可失败的初始值设定项,以安全地将一个整数类型转换为另一个整数类型
您可以传递一种类型来初始化另一种类型,如果初始化失败,它将返回nil
。返回的值是可选值,必须以常规方式展开
例如:
let i: Int64 = 12345678901
if let j = Int32(exactly: i) {
print("\(j) fits into an Int32")
} else {
// the initialization returned nil
print("\(i) is too large for Int32")
}
这允许您在转换失败时应用nil合并运算符以提供默认值:
// return 0 if rowid is too big to fit into an Int on this device
return Int(exactly: rowid) ?? 0
事实上,我也一直在使用这个框架,基本上我只是使用了相反的解决方案
Int64(yourInt)
(使用Xcode 7,Swift 2.0进行测试)如果您确信Int64
值可以精确表示为Int
,请使用Int(截断如果需要:)
,例如:
let salary: Int64 = 100000
let converted = Int(truncatingIfNeeded: salary)
if let converted = Int(exactly: salary) {
// in range
... converted ...
} else {
// out-of-range
...
}
对于以32位设备为目标的生成,Int
的范围限制为-2147483648到2147483647,与Int32
相同。超出该范围的值将悄悄地丢弃其高阶位。这会导致垃圾,通常是相反的符号
如果该值可能超出范围,并且您希望处理该情况,请使用Int(精确:)
,例如:
let salary: Int64 = 100000
let converted = Int(truncatingIfNeeded: salary)
if let converted = Int(exactly: salary) {
// in range
... converted ...
} else {
// out-of-range
...
}
在rowids的特定情况下,使用
Int64
而不是Int
是一个经过深思熟虑的API设计选择,而截断为Int
可能是一个bug。这是一个让人头疼的问题。这比Objective-C要愚蠢得多。但下面是如何做到的
如果您使用的是UInt64
,则可以这样做
let thatVarYouWantToConvert: UInt64 = 1
let myInt: Int = Int(exactly:thatVarYouWantToConvert ?? 0)
let thatVarYouWantToConvert: UInt64? = 1
let myInt: Int = Int(exactly:thatVarYouWantToConvert ?? 0) ?? 0
如果您使用的是UInt64?
,您可以这样做
let thatVarYouWantToConvert: UInt64 = 1
let myInt: Int = Int(exactly:thatVarYouWantToConvert ?? 0)
let thatVarYouWantToConvert: UInt64? = 1
let myInt: Int = Int(exactly:thatVarYouWantToConvert ?? 0) ?? 0
就像我说的,“这比Objective-C要愚蠢得多。”
在Swift 4.2、Xcode 10.2.1中测试,如果Int64的值大于2^31,且Int为32位,您认为会发生什么情况?@zaph溢出?我不知道…@zaph您能向我解释一下吗?如果Int64有一个使用超过32位的线索,而您将其分配给一个只有32位的Int,则会丢失额外的位,并且该值不正确。有一些资源可以阅读关于值是如何存储在内存中的,或者你可以学习规则。理解它可能更好,但每个人都有一个抽象级别,而不是下面的级别。还有一个抽象级别实际上是无法在下面看到的,例如知道RAM内存中的确切物理地址在今天的分配方案中,Value停留在当前普遍使用的编码级别。这就像试图将36盎司的瓶子中的内容倒入32盎司的瓶子中,最后4盎司的水将溢出到地板上并丢失。这可能会导致旧手机的性能变慢和库兼容性降低。如果您正在来回转换第四,毫无理由,这会给你的代码带来很多不必要的窃听、内存使用和潜在的错误。如果你知道你的应用程序不可能处理大于2^31-1的数字,那么最好只转换成
Int
。如果你可能不得不使用大于2^31-1的数字,请使用Int64
。除非必须,否则不要在运行时转换。在当前的Swift 3和4版本中,Int(truncatingBitPattern:)
不存在,Int(truncating:)
使用NSNumber
,因此不适用于Int64
。正确的调用现在是Int(truncatingIfNeeded:)
。我已经添加了一个单独的答案来澄清。@jedwidz,谢谢你的提醒。我修正了答案。