Ответ 1
Преобразование Int64
в Int
путем передачи значения Int64
в инициализатор Int
всегда будет работать на 64-разрядной машине и завершится сбоем на 32-разрядной машине, если целое число находится вне диапазона Int32.min... Int32.max
.
В целях безопасности используйте init(truncatingIfNeeded:)
(ранее известный как init(truncatingBitPattern:)
в более ранних версиях Swift) для преобразования значения:
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 вводит сбойные инициализаторы для безопасного преобразования одного целочисленного типа в другой. Используя 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")
}
Это позволяет вам применять оператор объединения nil для предоставления значения по умолчанию, если преобразование завершается неудачно:
// return 0 if rowid is too big to fit into an Int on this device
return Int(exactly: rowid) ?? 0