Error("'()'与'UInt8'不一样")使用Swift中的write函数将NSData字节写入NSOutputStream

StackOverflow https://stackoverflow.com//questions/25080661

  •  02-01-2020
  •  | 
  •  

我正在尝试基于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 不再保证底层数据将保存在单个连续内存块中。例如,根据文档为 didReceiveDataNSURLSessionDataDelegate 议定书:

因为 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(和关联的编译器)使用了一个更尴尬的结构来更新布尔引用以停止枚举。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top