2015-09-26 23 views
15

Tôi đã sử dụng SQLite.swift gần đây để xây dựng cơ sở dữ liệu ứng dụng của mình. Và tôi đang xác định tất cả các cột INTEGER của mình với loại Int64, như tài liệu giải thích.Tôi có thể truyền Int64 trực tiếp vào Int không?

Nhưng thỉnh thoảng tôi cần rằng Int64 chỉ là Int. Vì vậy, câu hỏi của tôi là, nếu tôi làm điều này:

//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 
} 

Nó có chính xác không?

Tất nhiên tôi đã thử nghiệm nó. Và nó hoạt động, nhưng tôi đã đọc this question in Stackoverflow

Và dường như tôi có thể có một vấn đề với các thiết bị 32 bit ...

Nếu điều này là sai, làm thế nào tôi có thể đúc Int64 vào Int?

+0

Nếu giá trị của Int64 là lớn hơn 2^31 và Int là 32-bit gì làm bạn nghĩ sẽ xảy ra? – zaph

+0

@zaph tràn? Tôi không biết ... –

+0

@zaph bạn có thể giải thích cho tôi không? –

Trả lời

22

Chuyển đổi một Int64-Int bằng cách thông qua các giá trị Int64 đến Int initializer sẽ luôn luôn làm việc trên một máy tính 64-bit, và nó sẽ sụp đổ trên một máy 32-bit nếu số nguyên nằm ngoài phạm vi Int32.min ... Int32.max.

Để an toàn sử dụng init(truncatingBitPattern) initializer để chuyển đổi các giá trị:

return Int(truncatingBitPattern: rowid) 

Trên một máy 64-bit, các truncatingBitPattern sẽ không làm gì cả; bạn sẽ chỉ nhận được một số Int (có cùng kích thước với số Int64).

Trên máy 32 bit, điều này sẽ vứt đi 32 bit trên cùng, nhưng tất cả đều là số 0, sau đó bạn không bị mất bất kỳ dữ liệu nào. Vì vậy, miễn là giá trị của bạn sẽ phù hợp với một số32 bit, bạn có thể làm điều này mà không làm mất dữ liệu. Nếu giá trị của bạn nằm ngoài phạm vi Int32.min ... Int32.max, giá trị này sẽ thay đổi giá trị của Int64 thành giá trị phù hợp trong một số32 bit nhưng sẽ không bị lỗi.


Bạn có thể xem cách hoạt động của tính năng này trong Sân chơi. Kể từ Int trong Sân chơi là một bit64 bit, bạn có thể sử dụng một cách rõ ràng Int32 để mô phỏng hành vi của hệ thống 32 bit.

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! 

Cập nhật cho Swift 3

Ngoài init(truncating:) mà vẫn hoạt động, Swift 3 giới thiệu initializers failable để chuyển đổi một cách an toàn một loại nguyên khác. Bằng cách sử dụng init?(exactly:), bạn có thể chuyển một loại để khởi tạo một loại khác và trả về nil nếu khởi tạo không thành công. Giá trị trả lại là một tùy chọn mà phải được bỏ trong các cách thông thường.

Ví dụ:

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") 
} 

này cho phép bạn áp dụng các nil coalescing hành để cung cấp một giá trị mặc định nếu việc chuyển đổi thất bại:

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

Như một vấn đề của thực tế, tôi đã cũng đang làm việc với khung này và về cơ bản tôi đã sử dụng giải pháp ngược lại. Bất cứ khi nào bạn thấy rằng các loại không phù hợp chỉ làm

Int64(yourInt) 

(thử nghiệm với Xcode 7, Swift 2.0)

Các vấn đề liên quan