2015-09-26 5 views
15

В последнее время я использую SQLite.swift для создания базы данных приложений. И я определяю все мои колонки INTEGER с типом Int64, как объясняет документация.Могу ли я использовать Int64 непосредственно в Int?

Но каждый раз в то время мне нужно, чтобы 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 
} 

Будет ли это правильно?

Конечно, я проверил его. И это действительно работает, но я читал this question in Stackoverflow

И мне кажется, что я мог бы иметь проблемы с 32 битами устройств ...

Если это не так, как я могу бросить Int64 в Int?

+0

Если значение Int64 больше, чем 2^31 и Int 32-бит, что делать вы думаете, что это произойдет? – zaph

+0

@zaph overflow? Я не знаю ... –

+0

@zaph вы можете мне объяснить? –

ответ

22

Int64 Преобразование в Int, передавая значение Int64 к Int инициализатора всегда будет работать на 64-битной машине, и он будет аварии на 32-битной машине, если число находится вне диапазона Int32.min ... Int32.max.

Для безопасности использования init(truncatingBitPattern) инициализатор для преобразования значения:

return Int(truncatingBitPattern: rowid) 

На 64-битной машине, то truncatingBitPattern не будет делать ничего; вы просто получите 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(truncatingBitPattern: i) // j = -539,222,987 
let k = Int32(i)      // crash! 

Обновление для Swift 3

В дополнение к init(truncating:), который до сих пор работает, Swift 3 вводит failable инициализаторами безопасно преобразовать один целочисленный тип в другой. Используя 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") 
} 

Это позволяет применить ноль сливающихся оператора указать значение по умолчанию, если преобразование не может быть:

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

На самом деле я также работал с этой картой, и в основном я просто использовал противоположное решение. Всякий раз, когда вы видите, что типы не совпадают вобще

Int64(yourInt) 

(протестирована с Xcode 7 Swift 2.0)

 Смежные вопросы

  • Нет связанных вопросов^_^