Swift: 无法将类型 'Self' 的值转换为预期的参数类型 'UnsafePointer<Void>'
Swift: cannot convert value of type 'Self' to expected argument type 'UnsafePointer<Void>'
我用 [Uint8]
数组做了很多工作。但是我经常不得不将它们重铸为 NSData
对象,以便与 iOS 框架(例如 CoreBluetooth
)交互。所以我有很多代码可能看起来像:
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 的次数越多——而且我真的很喜欢 Swift 的一些东西——我就越想起我在尝试理解大量无益的东西时的消极经历多年前,当我尝试使用大量泛型和其他东西尝试 C++ 时的编译器输出。所以请欧比旺帮我看看这里的光!
NSData(bytes:, length:)
将 UnsafePointer<Void>
作为第一个参数,您不能在此处传递任意 SequenceType
。
你可以传递一个Array
,它将作为
第一个数组元素。但是不能保证 Array
个元素
存储在连续内存中。
因此:
- 定义
Array
扩展而不是 Sequence
扩展。
- 使用
withUnsafeBufferPointer()
方法获取指针
到连续的数组存储。
可能的解决方案:
extension Array where Element : IntegerType {
var nsdata : NSData {
return self.withUnsafeBufferPointer {
NSData(bytes: [=10=].baseAddress, length: self.count * strideof(Element))
}
}
}
let input:[UInt8] = [0x60, 0x0D, 0xF0, 0x0D]
print(input.nsdata) // <600df00d>
Swift 目前不允许限制数组扩展
具体类型:
extension Array where Element == UInt8 { }
// error: same-type requirement makes generic parameter 'Element' non-generic
因此它被推广到任何符合IntegerType
的元素。
对于序列,您可以先转换为数组:
let data = Array(myUInt8sequence).nsdata
这似乎是你想要的。
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
我用 [Uint8]
数组做了很多工作。但是我经常不得不将它们重铸为 NSData
对象,以便与 iOS 框架(例如 CoreBluetooth
)交互。所以我有很多代码可能看起来像:
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 的次数越多——而且我真的很喜欢 Swift 的一些东西——我就越想起我在尝试理解大量无益的东西时的消极经历多年前,当我尝试使用大量泛型和其他东西尝试 C++ 时的编译器输出。所以请欧比旺帮我看看这里的光!
NSData(bytes:, length:)
将 UnsafePointer<Void>
作为第一个参数,您不能在此处传递任意 SequenceType
。
你可以传递一个Array
,它将作为
第一个数组元素。但是不能保证 Array
个元素
存储在连续内存中。
因此:
- 定义
Array
扩展而不是Sequence
扩展。 - 使用
withUnsafeBufferPointer()
方法获取指针 到连续的数组存储。
可能的解决方案:
extension Array where Element : IntegerType {
var nsdata : NSData {
return self.withUnsafeBufferPointer {
NSData(bytes: [=10=].baseAddress, length: self.count * strideof(Element))
}
}
}
let input:[UInt8] = [0x60, 0x0D, 0xF0, 0x0D]
print(input.nsdata) // <600df00d>
Swift 目前不允许限制数组扩展 具体类型:
extension Array where Element == UInt8 { }
// error: same-type requirement makes generic parameter 'Element' non-generic
因此它被推广到任何符合IntegerType
的元素。
对于序列,您可以先转换为数组:
let data = Array(myUInt8sequence).nsdata
这似乎是你想要的。
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