2016-03-22 72 views
2

我使用[Uint8]數組做了一堆工作。但我經常不得不將這些重寫爲NSData對象,以便與iOS框架(如CoreBluetooth)進行交互。所以我有很多的代碼可能看起來像:Swift:無法將類型'Self'的值轉換爲期望的參數類型'UnsafePointer <Void>'

var input:[UInt8] = [0x60, 0x0D, 0xF0, 0x0D] 
let data = NSData(bytes: input, length: input.count) 

由於勞累不必插入此額外let data = ...行的,我以爲我會只是延長這些陣列與計算物業辦的工作。然後我可以做這樣的事情:

aBluetoothPeriperal.write(myBytes.nsdata, ...) 

所以它基本上只是延長糖。我無法擴展陣列,但我可以擴展協議:

extension SequenceType where Generator.Element == UInt8 { 
    var nsdata:NSData { 
     return NSData(bytes: self, length: self.count) 
    } 
} 

其產生看起來像一個錯誤:

Playground execution failed: MyPlayground.playground:3:24: error: cannot convert value of type 'Self' to expected argument type 'UnsafePointer<Void>' (aka 'UnsafePointer<()>') 
       return NSData(bytes: self, length: self.count) 
           ^~~~ 

可悲的是,我越用斯威夫特 - 我真的很喜歡關於Swift的一些事情 - 我想起了越來越多的關於嘗試理解大量無用的編譯器輸出的負面經歷,這些經驗在我多年前嘗試使用C++和許多泛型和東西時遇到。所以請奧比萬,幫我看看這裏的燈光!

+0

你打算如何打電話給這樣的擴展?你可以添加調用代碼的樣子嗎? – ryantxr

回答

3

NSData(bytes:, length:)UnsafePointer<Void>作爲第一個參數,並且您無法在此傳遞任意SequenceType

可以通過Array這將作爲 第一個數組元素的地址傳遞。然而,不保證Array元素 被存儲在連續的存儲器中。

因此:

  • 定義一條Array延伸,而不是Sequence擴展。
  • 使用withUnsafeBufferPointer()方法獲取指向連續數組存儲的指針 。

可能的解決方案:

extension Array where Element : IntegerType { 
    var nsdata : NSData { 
     return self.withUnsafeBufferPointer { 
      NSData(bytes: $0.baseAddress, length: self.count * strideof(Element)) 
     } 
    } 
} 

let input:[UInt8] = [0x60, 0x0D, 0xF0, 0x0D] 
print(input.nsdata) // <600df00d> 

夫特目前不允許到陣列延伸 限制到一個具體類型:

extension Array where Element == UInt8 { } 
// error: same-type requirement makes generic parameter 'Element' non-generic 

因此它推廣到符合IntegerType任何元素。

對於序列你可以再做一個轉換到一個數組第一:

let data = Array(myUInt8sequence).nsdata 
+0

好的,這個工程,但我比以前有更多的問題!我認爲人們無法擴展模板化的結構,但必須在哪些細化方面擴展協議?但顯然,我錯了嗎?但是,讓我困惑的是你使用'IntegerType'而不是'UInt8'?我嘗試了UInt8,它變得瘋狂,因爲UInt8是一種類型而不是協議。 –

+0

另外,我不需要使用withUnsafeBufferPointer來使編譯器感到高興。如果我只是跳過該包裝並使用默認的NSData(bytes:self ...),會發生什麼不良行爲? –

+1

@TravisGriggs:從Xcode 7 beta 2開始,您可以擴展受限數組類型。但是,您可以將元素類型僅限制爲協議,而不是具體類型,這就是我選擇IntegerType的原因。 - 查找withUnsafeBufferPointer的在線幫助。它確保數組元素處於連續存儲中,否則不能保證。 –

1

這似乎做你想要什麼。

protocol ByteOnly: IntegerType {} 
extension UInt8: ByteOnly {} 

extension Array where Element: ByteOnly { 
    var n : NSData { return NSData(bytes: self, length: self.count) } 
} 
// does it work with UInt8 
var input5:[UInt8] = [0x61, 0x0D, 0xF1, 0x0D] 
let data5 = input5.n // YES 

// does it work on ints? 
var ints: [Int] = [3,4,5,6,7,8] 
let idata5 = ints.n // no 
+0

令人敬畏的加法。謝謝! –

相關問題