Error("'()'与'UInt8'不一样")使用Swift中的write函数将NSData字节写入NSOutputStream
题
我正在尝试基于Swift构建一个异步文件下载 埃里卡*萨顿的方法.但我需要它来处理更大的文件,所以我发现 这个关于使用NSOutputStream而不是NSData的答案, ,说得通。
但是,我无法让它发挥作用。当我尝试将NSData字节(在我的NSURLConnection didReceiveData函数中)添加到NSOutputStream写入函数时,我收到此错误: '()' is not identical to 'UInt8'
在这一排: bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite)
.
data.bytes
是那种类型的 ConstUnsafePointer<()>
而 .write()
函数期望类型为 ConstUnsafePointer<UInt8>
, ,所以从这个意义上说,错误是完全有道理的。但是由于我是iOS的新手,当然还有Swift编程,我无法弄清楚如何解决这个问题。
那么,我该如何转换 data.bytes: ConstUnsafePointer<()>
到 ConstUnsafePointer<UInt8>
alt.让这件事换个方式?
我的 didReceiveData
功能:
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
var bytesLeftToWrite: NSInteger = data.length
var bytesWritten: NSInteger = 0
while bytesLeftToWrite > 0 {
bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite)
if bytesWritten == -1 {
break
}
bytesLeftToWrite -= bytesWritten
let responseExpectedlenght: NSNumber = NSNumber(longLong: self.downloadResponse!.expectedContentLength)
let dataLength: NSNumber = NSNumber(long: data.length)
self.downloadProgressPercentage = ((dataLength / responseExpectedlenght) * 100)
println("Downloaded: \(self.downloadProgressPercentage)%")
}
}
解决方案
你可以用 UnsafePointer()
:
bytesWritten = self.downloadStream.write(UnsafePointer(data.bytes), maxLength: bytesLeftToWrite)
在你的写循环中也有一个问题,因为你总是写 初始 到输出流的数据对象的字节。
它可能看起来类似于此(未经测试):
var bytes = UnsafePointer<UInt8>(data.bytes)
var bytesLeftToWrite: NSInteger = data.length
while bytesLeftToWrite > 0 {
let bytesWritten = self.downloadStream.write(bytes, maxLength: bytesLeftToWrite)
if bytesWritten == -1 {
break // Some error occurred ...
}
bytesLeftToWrite -= bytesWritten
bytes += bytesWritten // advance pointer
// ...
}
其他提示
我建议你利用 enumerateByteRangesUsingBlock
, ,因为 NSData
不再保证底层数据将保存在单个连续内存块中。例如,根据文档为 didReceiveData
的 NSURLSessionDataDelegate
议定书:
因为
NSData
对象通常是从许多不同的数据对象拼凑而成的,只要可能,使用NSData
'的enumerateByteRangesUsingBlock:
迭代数据的方法,而不是使用bytes
方法(使NSData
对象到单个存储器块中)。
因此,例如,你可以做一个扩展 NSOutputStream
它写了一个 NSData
:
extension NSOutputStream {
/// Write contents of NSData to `NSOutputStream`
///
/// - parameter data: The `NSData` being written to the stream.
///
/// - returns: The number of bytes written. In case of error, returns -1.
func writeData(data: NSData) -> Int {
var totalBytesWritten = 0
data.enumerateByteRangesUsingBlock() {
buffer, range, stop in
var bytes = UnsafePointer<UInt8>(buffer)
var bytesWritten = 0
var bytesLeftToWrite = range.length
while bytesLeftToWrite > 0 {
bytesWritten = self.write(bytes, maxLength: bytesLeftToWrite)
if bytesWritten < 0 {
stop.initialize(true)
totalBytesWritten = -1
return
}
bytes += bytesWritten
bytesLeftToWrite -= bytesWritten
totalBytesWritten += bytesWritten
}
}
return totalBytesWritten
}
}
注意,在错误的情况下停止枚举的技术,即 stop.initialize(true)
, ,需要Xcode6beta4或更高版本。早期版本的Xcode(和关联的编译器)使用了一个更尴尬的结构来更新布尔引用以停止枚举。