Errore ("" () '' non è identico a 'UINT8' ") Scrittura di NSData Bytes su NSoutputStream utilizzando la funzione di scrittura in Swift

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

  •  02-01-2020
  •  | 
  •  

Domanda

Sto cercando di costruire un download di file asincrono in SWIFT sulla base del Metodo Erica Sadun . Ma ne ho bisogno per gestire i file più grandi, così ho trovato questa risposta sull'utilizzo di un nsoutputstream invece di nsdata , ha senso. < / P >.

Tuttavia, non riesco a farlo funzionare. Ottengo questo errore quando provo ad aggiungere i byte NSDATA (nella mia funzione NsurlConnection DidRekeDatata) alla funzione di scrittura NSOUTputStream: '()' is not identical to 'UInt8' su questa riga: bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite).

data.bytes è del tipo ConstUnsafePointer<()> e la funzione .write() si aspetta che il tipo sia generatoDicetagcode, quindi in questo senso, l'errore ha perfettamente senso. Ma dal momento che sono nuovo per iOS e ovviamente la programmazione rapida, non riesco a farti prendere la testa su come risolvere questo problema.

Quindi, come posso convertire il ConstUnsafePointer<UInt8> in data.bytes: ConstUnsafePointer<()> Alt. Fai questo lavoro in altro modo?

La mia funzione ConstUnsafePointer<UInt8>:

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

    }

}
.

È stato utile?

Soluzione

È possibile lanciare il puntatore con UnsafePointer():

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

C'è anche un problema nel tuo loop di scrittura, perché scrivi sempre il Iniziali Bytes dell'oggetto dati al flusso di uscita.

Dovrebbe probabilmente sembrare simile a questo (non testato):

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

    // ...
}
.

Altri suggerimenti

Suggerirei di avvalersi di enumerateByteRangesUsingBlock, poiché NSData non garantisce più che i dati sottostanti si terranno in un unico blocco di memoria contiguo. Ad esempio, in base alla documentazione per didReceiveData del protocollo NSURLSessionDataDelegate:

.

Poiché l'oggetto NSData viene spesso messo insieme da un numero di diversi oggetti di dati, quando possibile, utilizzare il metodo NSDatatagCoDetagCoDetagCoDetagCoDetaGCode enumerateByteRangesUsingBlock: per iterano attraverso i dati anziché utilizzare il metodo bytes (che appiatti l'oggetto NSData in un singolo blocco di memoria).

Pertanto, ad esempio, è possibile eseguire un'estensione del NSOutputStream che scrive il contenuto di un 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
    }

}
.

Nota, la tecnica di fermare l'enumerazione in caso di errore, vale a dire stop.initialize(true), richiede Xcode 6 Beta 4 o successive. Le versioni precedenti di Xcode (e compilatore associato) hanno utilizzato una costruzione più imbarazzante per aggiornare il riferimento booleano per fermare l'enumerazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top