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

Ren*_*ira 23 ios swift sqlite.swift

我最近一直在使用SQLite.swift来构建我的app数据库.我正在INTEGERInt64类型定义我的所有列,就像文档解释的那样.

但每隔一段时间我就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
}
Run Code Online (Sandbox Code Playgroud)

这是对的吗?

当然我测试了它.它确实有效,但我正在Stackoverflow中阅读这个问题

似乎我可能遇到32位设备的问题......

如果这是错的,我怎么能Int64投入Int

vac*_*ama 35

通过将值传递给初始化程序Int64来转换为将始终在64位计算机上运行,​​如果整数超出范围,它将在32位计算机上崩溃.IntInt64IntInt32.min ... Int32.max

为了安全起见,使用init(truncatingIfNeeded:)初始化程序(以前称为init(truncatingBitPattern:)早期的Swift版本)来转换值:

return Int(truncatingIfNeeded: rowid)
Run Code Online (Sandbox Code Playgroud)

在64位机器上,它truncatingIfNeeded什么都不做; 你会得到一个Int(与大小相同Int64).

在32位机器上,这将丢弃前32位,但它们都是零,然后你没有丢失任何数据.因此,只要您的值适合32位Int,就可以在不丢失数据的情况下执行此操作.如果您的值超出范围Int32.min ... Int32.max,则会将值更改Int64为适合32位的值Int,但不会崩溃.


您可以在Playground中看到它的工作原理.由于Int在Playground中是64位Int,因此可以明确使用an 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!
Run Code Online (Sandbox Code Playgroud)

更新Swift 3/4

除此之外init(truncatingIfNeeded:),Swift 3还引入了可用的初始值设定项,可以将一个整数类型安全地转换为另一个整数类型.通过使用,init?(exactly:)您可以传递一种类型来初始化另一种类型,并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")
}
Run Code Online (Sandbox Code Playgroud)

这允许您应用nil合并运算符以在转换失败时提供默认值:

// return 0 if rowid is too big to fit into an Int on this device
return Int(exactly: rowid) ?? 0
Run Code Online (Sandbox Code Playgroud)

  • 在当前的 Swift 3 和 4 版本中,“Int(truncatingBitPattern:)”不存在,并且“Int(truncating:)”采用“NSNumber”,因此不适用于“Int64”。现在正确的调用是“Int(truncatingIfNeeded:)”。我添加了一个单独的答案来澄清。 (2认同)

jed*_*idz 5

如果您确信该Int64值可以完全表示为Int,请使用Int(truncatingIfNeeded:),例如:

let salary: Int64 = 100000
let converted = Int(truncatingIfNeeded: salary)
Run Code Online (Sandbox Code Playgroud)

对于针对 32 位设备的构建, 的范围Int限制为 -2147483648 到 2147483647,与Int32. 超出该范围的值将悄悄地丢弃其高位。这会产生垃圾,而且通常具有相反的符号。

如果该值可能超出范围,并且您想要处理该情况,请使用Int(exactly:),例如:

if let converted = Int(exactly: salary) {
    // in range
    ... converted ...
} else {
    // out-of-range
    ...
}
Run Code Online (Sandbox Code Playgroud)

在 rowids 的特定情况下,使用Int64而不是Int故意的 API 设计选择,并且截断到Int可能是一个错误。