Erreur (« '()' n'est pas identique à 'UInt8' ») lors de l'écriture d'octets NSData dans NSOutputStream à l'aide de la fonction d'écriture dans Swift

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

  •  02-01-2020
  •  | 
  •  

Question

J'essaie de créer un téléchargement de fichiers asynchrone dans Swift basé sur La méthode d'Erica Sadun.Mais j'en ai besoin pour gérer des fichiers plus gros, alors j'ai trouvé cette réponse sur l'utilisation d'un NSOutputStream au lieu de NSData, logique.

Cependant, je n'arrive pas à le faire fonctionner.J'obtiens cette erreur lorsque j'essaie d'ajouter les octets NSData (dans ma fonction NSURLConnection didReceiveData) à la fonction d'écriture NSOutputStream : '()' is not identical to 'UInt8' sur cette ligne : bytesWritten = self.downloadStream.write(data.bytes, maxLength: bytesLeftToWrite).

data.bytes est du genre ConstUnsafePointer<()> et le .write() la fonction s'attend à ce que le type soit ConstUnsafePointer<UInt8>, donc en ce sens, l'erreur est parfaitement logique.Mais comme je suis nouveau sur iOS et bien sûr sur la programmation Swift, je n'arrive pas à comprendre comment résoudre ce problème.

Alors, comment puis-je convertir le data.bytes: ConstUnsafePointer<()> à ConstUnsafePointer<UInt8> alt.faire en sorte que cela fonctionne d'une autre manière ?

Mon didReceiveData fonction:

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

    }

}
Était-ce utile?

La solution

Vous pouvez lancer le pointeur avec UnsafePointer():

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

Il y a aussi un problème dans votre boucle d'écriture, car vous écrivez toujours leinitial octets de l'objet de données dans le flux de sortie.

Cela devrait probablement ressembler à ceci (non testé) :

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

    // ...
}

Autres conseils

Je suggérerais de profiter de enumerateByteRangesUsingBlock, parce que NSData ne garantit plus que les données sous-jacentes seront conservées dans un seul bloc de mémoire contigu.Par exemple, selon la documentation de didReceiveData de la NSURLSessionDataDelegate protocole:

Parce que le NSData L'objet est souvent reconstitué à partir d'un certain nombre d'objets de données différents. Dans la mesure du possible, utilisez NSDatac'est enumerateByteRangesUsingBlock: méthode pour parcourir les données plutôt que d'utiliser la bytes méthode (qui aplatit le NSData objet dans un seul bloc mémoire).

Ainsi, par exemple, vous pourriez faire une extension de NSOutputStream qui écrit le contenu d'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
    }

}

A noter, la technique d'arrêt de l'énumération en cas d'erreur, à savoir stop.initialize(true), nécessite Xcode 6 bêta 4 ou version ultérieure.Les versions antérieures de Xcode (et du compilateur associé) utilisaient une construction plus délicate pour mettre à jour la référence booléenne afin d'arrêter l'énumération.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top