2016-09-24 14 views
9

Theo tài liệu của Dữ liệu trong Swift 3, có một trình khởi tạo mà tôi có thể sử dụng để tạo Dữ liệu từ UnsafeRawPointer. Điều tôi cần thực sự là ngược lại. Tôi có một dữ liệu, và tôi muốn tạo ra một UnsafeRawPointer trỏ đến các byte của dữ liệu. Dưới đây là những gì tôi đang làm ngay bây giờ:Trong Swift 3, làm cách nào để lấy UnsafeRawPointer từ Dữ liệu?

1. let data = <from some where> 
2. let unsafePointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count) 
3. unsafePointer.initialize(to: 0, count: data.count) // is this necessary? 
4. data.copyBytes(to: unsafePointer, count: data.count) 
5. let unsafeRawPointer = unsafePointer.deinitialize() // this is of the type UnsafeMutalbleRawPointer, and I can use it where UnsafeRawPointer is needed. 

Tôi đã xác minh rằng mã này hoạt động trong Xcode Playground. Mã này thậm chí hoạt động mà không có số dòng 3. Tôi không chắc chắn sự khác biệt có hoặc không có dòng. Dù sao, câu hỏi của tôi là, tôi đang làm đúng cho những gì tôi muốn? Có cách nào đơn giản hơn để làm điều đó không?

Trả lời

16

withUnsafeBytes() mang đến cho bạn một (gõ) trỏ đến byte, này có thể được chuyển đổi sang một con trỏ liệu:

let data = <Data from somewhere> 
data.withUnsafeBytes { (u8Ptr: UnsafePointer<UInt8>) in 
    let rawPtr = UnsafeRawPointer(u8Ptr) 
    // ... use `rawPtr` ... 
} 

Con trỏ chỉ có giá trị trong suốt thời gian của cuộc gọi đến đóng cửa.

Ngoài ra, bạn có thể là cầu nối để NSData và truy cập vào các byte thô:

let nsData = data as NSData 
let rawPtr = nsData.bytes 

Bây giờ con trỏ có giá trị trong phạm vi cùng một nơi nsData là hợp lệ.

+0

Các giải pháp trông đẹp hơn và sạch hơn so với tôi. Và thứ hai là khá thẳng về phía trước quá. – Jake

+0

Có vẻ như 'withUnsafeBytes' là một trong những quyền đối với tôi. Có vẻ an toàn hơn giải pháp NSData – Jake

+0

'withUnsafeBytes' có vẻ bị giới hạn. Điều gì xảy ra nếu tôi muốn một số gợi ý để thực hiện các hoạt động trên tất cả chúng? – ryantxr

4

Kiểm tra the latest reference.

Chúng tôi không thể tìm thấy phương pháp hoặc thuộc tính truy xuất UnsafeRawPointer từ số Data.

Vì vậy, đối với thay thế: func withUnsafeBytes((UnsafePointer) -> ResultType)

Bạn có thể viết một cái gì đó như thế này:

let data: Data = <initialize it as you like> 

data.withUnsafeBytes {(uint8Ptr: UnsafePointer<UInt8>) in 
    let rawPtr = UnsafeRawPointer(uint8Ptr) 
    //`rawPtr` (and `uint8Ptr`) is guaranteed to be valid in this closure 
    //... 
    //You have no need manage `rawPtr`. 
} 

(Ồ, điều này cũng giống như nửa đầu của câu trả lời Martin R).


Nhưng nếu bạn muốn giữ UnsafeRawPointer hợp lệ trong một khoảng thời gian dài hơn khi đóng, bạn cần tạo một bản sao của nt của Data:

Ví dụ:

let uint8Ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count) 
uint8Ptr.initialize(from: data) //<-copying the data 
//You need to keep `uint8Ptr` and `data.count` for future management 
let uint8PtrCount = data.count 
//You can convert it to `UnsafeRawPointer` 
let rawPtr = UnsafeRawPointer(uint8Ptr) 
//Use `rawPtr` while `uint8Ptr` is valid 
//... 
//Deinitialize and deallocate the region 
uint8Ptr.deinitialize(count: uint8PtrCount) 
uint8Ptr.deallocate(capacity: uint8PtrCount) 

(Bạn có thể nhận UnsafeMutableRawPointer như một giá trị trở lại của deinitialize(count:), nhưng khu vực này là trong tình trạng uninitialized, vì vậy bạn không nên truy cập vào khu vực.)

+0

Cảm ơn hai giải pháp. Cả hai đều trông đẹp hơn tôi. – Jake

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