I'm trying to build an asynchronous file download in Swift based on the Erica Sadun's method. But I need it to handle bigger files, so I found this answer about using a NSOutputStream instead of NSData, makes sense.
However, I can't get it to work. I get this error when I try adding the NSData bytes (in my NSURLConnection didReceiveData function) to the NSOutputStream write function: '()' is not identical to 'UInt8'
on this row: bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite)
.
data.bytes
is of the type ConstUnsafePointer<()>
and the .write()
function expects the type to be ConstUnsafePointer<UInt8>
, so in that sense, the error make perfect sense. But since I'm new to iOS and of course Swift programming, I can't get my head around how to fix this.
So, how do I convert the data.bytes: ConstUnsafePointer<()>
to ConstUnsafePointer<UInt8>
alt. make this work some other way?
My didReceiveData
function:
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)%")
}
}
You can cast the pointer with
UnsafePointer()
:There is also a problem in your write loop, because you always write the initial bytes of the data object to the output stream.
It should probably look similar to this (untested):
I'd would suggest availing yourself of
enumerateByteRangesUsingBlock
, becauseNSData
no longer guarantees that the underlying data will be held in a single contiguous memory block. For example, according to the documentation fordidReceiveData
of theNSURLSessionDataDelegate
protocol:Thus, for example, you could do an extension of
NSOutputStream
that writes the contents of aNSData
:Note, the technique of stopping the enumeration in case of error, namely
stop.initialize(true)
, requires Xcode 6 beta 4 or later. Earlier versions of Xcode (and associated compiler) used a more awkward construction for updating the boolean reference to stop the enumeration.