Ошибка (“'()' не идентична 'UInt8'”) при записи байтов NSData в NSOutputStream с использованием функции записи в Swift

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> альт.заставить это работать как-то по-другому?

Мой 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 больше не гарантирует, что базовые данные будут храниться в одном непрерывном блоке памяти.Например, согласно документации для didReceiveData из числа NSURLSessionDataDelegate протокол:

Потому что NSData объект часто составляется из нескольких различных объектов данных, по возможности используйте NSData’s 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), требуется Xcode 6 beta 4 или более поздняя версия.Более ранние версии Xcode (и связанного с ним компилятора) использовали более неудобную конструкцию для обновления логической ссылки, чтобы остановить перечисление.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top