Erro ("'()' não é idêntico ao 'UInt8'") escrita NSData bytes para NSOutputStream usando a função de escrita Rápida

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

  •  02-01-2020
  •  | 
  •  

Pergunta

Eu estou tentando construir um assíncrona download de arquivo no Swift com base no Erica Sadun do método.Mas eu preciso dele para lidar com arquivos maiores, então eu encontrei esta resposta sobre o uso de um NSOutputStream em vez de NSData, faz sentido.

No entanto, eu não posso fazê-lo funcionar.Eu recebo este erro quando eu tento adicionar NSData bytes (no meu NSURLConnection didReceiveData função) para o NSOutputStream de escrever a função: '()' is not identical to 'UInt8' por esta linha: bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite).

data.bytes é do tipo ConstUnsafePointer<()> e o .write() função espera que o tipo a ser ConstUnsafePointer<UInt8>, então, nesse sentido, o erro faz perfeito sentido.Mas desde que eu sou novo para o iOS e, claro, Swift programação, eu não posso colocar minha cabeça em torno de como consertar isso.

Então, como faço para converter o data.bytes: ConstUnsafePointer<()> para ConstUnsafePointer<UInt8> alt.fazer este trabalho de alguma outra forma?

Meu didReceiveData função:

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)%")

    }

}
Foi útil?

Solução

Você pode converter o ponteiro com UnsafePointer():

bytesWritten = self.downloadStream.write(UnsafePointer(data.bytes), maxLength: bytesLeftToWrite)

Há também um problema em sua gravação de loop, porque você sempre escrever o inicial bytes do objeto de dados para o fluxo de saída.

Ele provavelmente deve parecer semelhante a este (não testado):

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

    // ...
}

Outras dicas

Eu gostaria de sugerir valendo-se de enumerateByteRangesUsingBlock, porque NSData já não garante que a base de dados será realizada em um único bloco de memória contígua.Por exemplo, de acordo com a documentação didReceiveData do NSURLSessionDataDelegate protocolo:

Porque o NSData objeto geralmente é reunido a partir de um número de diferentes objetos de dados, sempre que possível, use NSData's enumerateByteRangesUsingBlock: método para iterar através de dados em vez de utilizar o bytes método (o que achata a NSData objeto em um único bloco de memória).

Assim, por exemplo, você poderia fazer uma extensão de NSOutputStream que escreve o conteúdo de uma 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
    }

}

Observação, a técnica de parar a enumeração, em caso de erro, a saber, stop.initialize(true), requer Xcode 6 beta 4 ou posterior.Versões anteriores do Xcode (e associados do compilador), usou um mais estranho de construção para atualizar o valor booleano de referência para parar a enumeração.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top