Разделение данных на куски в Swift 3

Мне нужно отправить изображения, считанные из фотобиблиотеки, по сети — кусками по 5 МБ.

Я читаю изображение из библиотеки, используя: PHImageManager.requestImageData(for:options:resultHandler:) и получаю объект Data. Затем я хотел бы эффективно разделить данные на куски (без копирования памяти). Как лучше всего это сделать?

Это то, что у меня есть до сих пор:

    imageData.withUnsafeBytes { (unsafePointer: UnsafePointer<UInt8>) -> Void in

        let totalSize = data.endIndex
        var offset = 0

        while offset < totalSize {
            let chunkSize = offset + uploadChunkSize > totalSize ? totalSize - offset : uploadChunkSize
            let chunk = Data(bytesNoCopy: unsafePointer, count: chunkSize, deallocator: Data.Deallocator.none)

            // send the chunk...

           offset += chunkSize
        }
    }

Однако я получаю эту ошибку во время компиляции:

Не удается преобразовать значение типа UnsafePointer в ожидаемый тип аргумента UnsafeMutableRawPointer.

Если я использую mutableBytes:

data.withUnsafeMutableBytes { (unsafePointer: UnsafeMutablePointer<UInt8>) -> Void in... }

Затем я получаю ошибку времени компиляции:

Невозможно использовать изменяемый элемент для неизменяемого значения: «данные» — это константа «let»

Что правильно, так как я не очень хочу вносить изменения в данные изображения. Я хочу отправить только один кусок за раз.

Есть лучший способ сделать это?


person GK100    schedule 03.03.2017    source источник
comment
было бы хорошо, если бы вы отметили свое решение. Спасибо   -  person John    schedule 17.08.2017


Ответы (2)


Привет!

Мне нужно такое же поведение, и я придумал это решение. Вы правильно указали на ошибку, и решение состоит в том, чтобы просто создать UnsafeMutableRawPointer с адресом UnsafePointer. Это самое быстрое решение, которое я нашел.

Еще одна вещь — добавить смещение к базовому адресу mutRawPointer при создании чанка.

Данные размером 50 МБ фрагментами по 2 МБ занимают ~ 0,009578 с.

func createChunks(forData: Data) {

    imageData.withUnsafeBytes { (u8Ptr: UnsafePointer<UInt8>) in
        let mutRawPointer = UnsafeMutableRawPointer(mutating: u8Ptr)
        let uploadChunkSize = 2097152
        let totalSize = imageData.count
        var offset = 0

        while offset < totalSize {

            let chunkSize = offset + uploadChunkSize > totalSize ? totalSize - offset : uploadChunkSize
            let chunk = Data(bytesNoCopy: mutRawPointer+offset, count: chunkSize, deallocator: Data.Deallocator.none)
            offset += chunkSize
        }
    }
}
person John    schedule 21.06.2017
comment
Это хорошо работает для небольших файлов, но если вы хотите разделить файл размером 4 ГБ, вам придется загружать его весь в память, что в большинстве случаев может не работать. - person 0x6A75616E; 14.05.2018

Инициализатору Data(bytesNoCopy: ... требуется изменяемый указатель. Измените код на следующий, чтобы он работал:

imageData.withUnsafeMutableBytes { (unsafePointer: UnsafeMutablePointer<UInt8>) -> Void in
    // your code
}
person Adam    schedule 03.03.2017