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