Ios 我可以直接将Int64转换为Int吗?

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

我最近一直在使用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, 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,谢谢你的提醒。我修正了答案。