错误(“'()”与“UInt8”不同)“使用Swift中的写入函数将NSData字节写入NSOutputStream

我试图build立一个基于埃里卡Sadun的方法在Swift中的asynchronous文件下载。 但我需要它来处理更大的文件,所以我find了有关使用NSOutputStream而不是NSData的答案 ,这是有道理的。

但是,我不能得到它的工作。 (NSURLConnection didReceiveData函数中)向NSOutputStream写入函数添加NSData字节时出现此错误: '()' is not identical to 'UInt8'此行上的'()' is not identical to 'UInt8'bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite)

data.bytes的types是ConstUnsafePointer<()> ,而.write()函数期望types是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) 

在写循环中也存在一个问题,因为您始终将数据对象的初始字节写入输出stream。

它应该看起来类似于(未经testing):

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

我会build议利用enumerateByteRangesUsingBlock自己,因为NSData不再保证底层数据将被保存在一个连续的内存块。 例如,根据NSURLSessionDataDelegate协议的NSURLSessionDataDelegate文档:

因为NSData对象通常是从许多不同的数据对象拼凑在一起,所以只要有可能,使用NSDataenumerateByteRangesUsingBlock:方法遍历数据,而不是使用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) ,需要Xcode 6 beta 4或更高版本。 早期版本的Xcode(和相关的编译器)使用了一个更笨拙的构造来更新布尔引用来停止枚举。