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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32793460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:49:51  来源:igfitidea点击:

Can I cast Int64 directly into Int?

iosswiftsqlite.swift

提问by Renato Parreira

I've been using SQLite.swift lately to build my app database. And I'm defining all my INTEGERcolumns with a Int64type, like the documentation explains.

我最近一直在使用 SQLite.swift 来构建我的应用程序数据库。我正在INTEGER用一个Int64类型定义我的所有列,就像文档解释的那样。

But every once in a while I need that Int64to be just Int. So my question is, if I do this:

但每隔一段时间,我需要那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
}

Will it be correct?

会正确吗?

Of course I tested it. And it does works, but I was reading this question in Stackoverflow

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

And it seems that I could have a problem with 32 bits devices...

似乎我在使用 32 位设备时可能会遇到问题...

If this is wrong, how can I cast Int64into Int?

如果这是错误的,我该如何Int64投入Int

回答by vacawama

Converting an Int64to Intby passing the Int64value to the Intinitializer 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.

通过将值传递给初始值设定项来转换Int64to将始终在 64 位机器上工作,如果整数超出范围,它将在 32 位机器上崩溃。IntInt64IntInt32.min ... Int32.max

For safety use the init(truncatingIfNeeded:)initializer (formerly known as init(truncatingBitPattern:)in earlier Swift versions) to convert the value:

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

return Int(truncatingIfNeeded: rowid)

On a 64-bit machine, the truncatingIfNeededwill do nothing; you will just get an Int(which is the same size as an Int64anyway).

在 64 位机器上,truncatingIfNeeded什么都不做;你只会得到一个IntInt64无论如何都与一个相同的大小)。

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 Int64into something that fits in a 32-bit Int, but it will not crash.

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



You can see how this works in a Playground. Since Intin a Playground is a 64-bit Int, you can explicitly use an Int32to simulate the behavior of a 32-bit system.

您可以在 Playground 中看到这是如何工作的。由于Int在 Playground 中是 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!


Update for Swift 3/4

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 nilif the initialization fails. The value returned is an optional which must be unwrapped in the usual ways.

除了init(truncatingIfNeeded:)仍然有效之外,Swift 3 引入了可失败的初始化器来安全地将一种整数类型转换为另一种。通过使用init?(exactly:)您可以传递一种类型来初始化另一种类型,nil如果初始化失败则返回。返回的值是一个可选的,必须以通常的方式解包。

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 operatorto supply a default value if the conversion fails:

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

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

回答by jedwidz

Ifyou're confident that the Int64value can be represented exactly as an Int, use Int(truncatingIfNeeded:), e.g.:

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

let salary: Int64 = 100000
let converted = Int(truncatingIfNeeded: salary)

For builds targeting 32-bit devices, the range for Intis 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.

对于面向 32 位设备的构建,范围Int限制为 -2147483648 到 2147483647,与Int32. 超出该范围的值将悄悄地丢弃其高位。这会导致垃圾,通常是相反的符号。

If the value might be out of range, and you want to handle that condition, use Int(exactly:), e.g.:

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

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

In the specific case of rowids, using Int64rather than Intwas a deliberate API design choice, and truncating to Intcould be a bug.

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

回答by Alex Zavatone

It's a pain in the ass. It's monumentally stupider than in Objective-C. But here is how you do it.

这是一个痛苦的屁股。它比在 Objective-C 中愚蠢得多。但这是你如何做到的。

If you are using a UInt64, you do it like this.

如果您正在使用 a UInt64,您可以这样做。

let thatVarYouWantToConvert: UInt64 = 1
let myInt: Int = Int(exactly:thatVarYouWantToConvert ?? 0)

If you are using a UInt64?, you do it like this.

如果您正在使用 a UInt64?,您可以这样做。

let thatVarYouWantToConvert: UInt64? = 1
let myInt: Int = Int(exactly:thatVarYouWantToConvert ?? 0) ?? 0

Like I said, "It's monumentally stupider than in Objective-C."

就像我说的,“它比 Objective-C 愚蠢得多。”

Tested in Swift 4.2, Xcode 10.2.1

在 Swift 4.2、Xcode 10.2.1 中测试

回答by René Blaser

As a matter of fact I've been working with this framework too, and basically I just used the opposite solution. Whenever you see that types don't match just do

事实上,我也一直在使用这个框架,基本上我只是使用了相反的解决方案。每当你看到类型不匹配时,就做

Int64(yourInt) 

(tested with Xcode 7, Swift 2.0)

(使用 Xcode 7、Swift 2.0 测试)