I've been using SQLite.swift lately to build my app database. And I'm defining all my INTEGER
columns with a Int64
type, like the documentation explains.
But every once in a while I need that Int64
to be just Int
. So my question is, if I do this:
//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 }
Will it be correct?
Of course I tested it. And it does works, but I was reading this question in Stackoverflow
And it seems that I could have a problem with 32 bits devices...
If this is wrong, how can I cast Int64
into Int
?
string to int/int64Use strconv. ParseInt to parse a decimal string (base 10 ) and check if it fits into an int64. The two numeric arguments represent a base (0, 2 to 36) and a bit size (0 to 64).
An int value can be converted into bytes by using the method int. to_bytes().
Int64 is an immutable value type that represents signed integers with values that range from negative 9,223,372,036,854,775,808 (which is represented by the Int64. MinValue constant) through positive 9,223,372,036,854,775,807 (which is represented by the Int64.
Converting an Int64
to Int
by passing the Int64
value to the Int
initializer will always work on a 64-bit machine, and it will crash on a 32-bit machine if the integer is outside of the range Int32.min ... Int32.max
.
For safety use the init(truncatingIfNeeded:)
initializer (formerly known as init(truncatingBitPattern:)
in earlier Swift versions) to convert the value:
return Int(truncatingIfNeeded: rowid)
On a 64-bit machine, the truncatingIfNeeded
will do nothing; you will just get an Int
(which is the same size as an Int64
anyway).
On a 32-bit machine, this will throw away the top 32 bits, but it they are all zeroes, then you haven't lost any data. So as long as your value will fit into a 32-bit Int
, you can do this without losing data. If your value is outside of the range Int32.min ... Int32.max
, this will change the value of the Int64
into something that fits in a 32-bit Int
, but it will not crash.
You can see how this works in a Playground. Since Int
in a Playground is a 64-bit Int
, you can explicitly use an Int32
to simulate the behavior of a 32-bit system.
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!
Update for Swift 3/4
In addition to init(truncatingIfNeeded:)
which still works, Swift 3 introduces failable initializers to safely convert one integer type to another. By using init?(exactly:)
you can pass one type to initialize another, and it returns nil
if the initialization fails. The value returned is an optional which must be unwrapped in the usual ways.
For example:
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") }
This allows you to apply the nil coalescing operator to supply a default value if the conversion fails:
// return 0 if rowid is too big to fit into an Int on this device return Int(exactly: rowid) ?? 0
If you're confident that the Int64
value can be represented exactly as an Int
, use Int(truncatingIfNeeded:)
, e.g.:
let salary: Int64 = 100000 let converted = Int(truncatingIfNeeded: salary)
For builds targeting 32-bit devices, the range for Int
is limited to -2147483648 through 2147483647, the same as Int32
. Values outside of that range will quietly have their high-order bits discarded. This results in garbage, often of the opposite sign.
If the value might be out of range, and you want to handle that condition, use Int(exactly:)
, e.g.:
if let converted = Int(exactly: salary) { // in range ... converted ... } else { // out-of-range ... }
In the specific case of rowids, using Int64
rather than Int
was a deliberate API design choice, and truncating to Int
could be a bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With