Почему ожидалось декодирование данных, но вместо этого я нашел массив У ​​меня нет массивов в моем коде

У меня есть кодируемая структура:

struct Foo: Codable {
    let rect: CGRect
    let image: UIImage

    init(rect: CGRect, image: UIImage) {
        self.rect = rect
        self.image = image
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(rect, forKey: .rect)
        try container.encode(UIImagePNGRepresentation(image), forKey: .image)
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        rect = try container.decode(CGRect.self, forKey: .rect)
        image = try UIImage(data: container.decode(Data.self, forKey: .image))!
    }

    enum CodingKeys : CodingKey {
        case rect
        case image
    }
}

Теперь я создаю Foo и пытаюсь его закодировать и расшифровать:

let image = UIImage(named: "my_image")
let foo = Foo(rect: .zero, image: image!)
let encoder = PropertyListEncoder()
let data = try! encoder.encode(foo)
let decoder = PropertyListDecoder()
try! decoder.decode(Foo.self, from: data)

Теперь в строке decode возникает эта ошибка:

Swift.DecodingError.typeMismatch (Foundation.Data, Swift.DecodingError.Context (codingPath: [__lldb_expr_244.Foo.CodingKeys.image], debugDescription: «Ожидается декодирование данных, но вместо этого обнаружен массив.», LowerError: nil))

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

Data() is Codable

оценивается как истина, поэтому кодировщики теоретически должны иметь возможность en / декодировать Data. Почему он стал массивом?

Изменить: я использую Xcode 9.1

Вот my_image:

введите описание изображения здесь


person Sweeper    schedule 14.01.2018    source источник
comment
Пробовал такой код в новом проекте, ошибок не вижу.   -  person Andrea Mugnaini    schedule 14.01.2018
comment
@AndreaMugnaini Можешь запустить его на детской площадке?   -  person Sweeper    schedule 14.01.2018
comment
Работает нормально, конечно, мне пришлось добавить изображение в Playground- ›Ресурсы   -  person Andrea Mugnaini    schedule 14.01.2018
comment
Это странно ... Я подожду и посмотрю, смогут ли другие воспроизвести это.   -  person Sweeper    schedule 14.01.2018
comment
Хорошо, а пока вы хотите проверить мой тест: github.com/mugx/playgroundtest   -  person Andrea Mugnaini    schedule 14.01.2018
comment
Я удалил другой комментарий, потому что ошибался. Код должен работать.   -  person vadian    schedule 17.01.2018
comment
@vadian Можете не воспроизвести? Это странно. Я вставил код, который написал Андреа Мугнанини, на свою игровую площадку, и произошло то же самое. Может ли это иметь какое-то отношение к моему региону или что-то в этом роде?   -  person Sweeper    schedule 17.01.2018
comment
Да, воспроизвести могу, тестировал на детской площадке. Я бы попробовал другой образ.   -  person vadian    schedule 17.01.2018
comment
Мне тоже кажется, что все работает, я предполагаю, что это либо что-то внутри Xcode9.1 (я тестирую против 9.2), либо что-то с изображением, можете ли вы прикрепить фактическое изображение, которое вы используете здесь, чтобы исключить эту часть?   -  person Mostafa Berg    schedule 17.01.2018
comment
@ MostafaTorbjørnBerg, это просто моя аватарка. Версия Xcode не должна иметь значения, верно? Кажется, проблема возникает быстро.   -  person Sweeper    schedule 17.01.2018
comment
Ясно, у вас есть какое-нибудь другое изображение, которое воспроизводится не на частной картинке? ну, Swift может быть таким же, но компилятор Swift и Swift SDK обычно включают изменения и исправления, поэтому он не всегда на 100% одинаков.   -  person Mostafa Berg    schedule 17.01.2018
comment
@ MostafaTorbjørnBerg Это не личная фотография. Вы можете просто зайти в мой профиль и скачать его. Во всяком случае, отредактировал вопрос.   -  person Sweeper    schedule 17.01.2018
comment
Отлично, я подумал, что это похоже на картинку на Facebook или около того;), Хорошо, попробовал сейчас, но не могу воспроизвести, я попробую загрузить Xcode 9.1 и посмотрю, начнут ли у меня проблемы, скоро сообщу   -  person Mostafa Berg    schedule 17.01.2018
comment
У меня работает на игровой площадке Xcode 9.2. По какой причине вы не можете обновиться? Также: протестируйте с другим изображением. Ошибка сохраняется?   -  person Gereon    schedule 17.01.2018
comment
Я проверил другое изображение в формате JPG, и ошибка не исчезла. И да, я могу обновить, но мне просто любопытно, почему это так. @Gereon   -  person Sweeper    schedule 17.01.2018
comment
@Sweeper хорошие новости, я тестировал с Xcode 9.1, и теперь я вижу вашу ошибку, это означает, что она решена в Xcode 9.2, я сейчас посмотрю и выясню, почему это происходит на 9.1 :)   -  person Mostafa Berg    schedule 17.01.2018


Ответы (1)


Я уверен, что это ошибка, похоже, проблема во время процесса кодирования, при кодировании данных UIImagePNGRepresentation, которые возвращаются как Optional, все идет совсем не так, если вы измените метод encode, чтобы заставить данные вроде этого:

container.encode(UIImagePNGRepresentation(image)!, forKey: .image)

вместо:

container.encode(UIImagePNGRepresentation(image), forKey: .image)

Все будет работать как в Xcode 9.1, так и в 9.2, если вы оставите данные необязательными, как есть, кодирование будет работать только в 9.2 и выйдет из строя 9.1, по какой-то причине размер данных изображения будет удвоен в 9.1.

Я почти уверен, что это этот отчет об ошибке на swift.org

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

Так что простой способ - принудительно ввести UIImagePNGRepresentation(..) данные или обновить до 9.2, где эта ошибка исправлена.

Надеюсь, это ответило на ваш вопрос, действительно очень интересная находка!

person Mostafa Berg    schedule 17.01.2018
comment
Вы узнали, почему он находит массив? - person Sweeper; 17.01.2018
comment
может быть много причин, и я не вдавался в подробности PR, который это исправляет, но я почти уверен, если вы посмотрите на здесь вы увидите, что значения не были упакованы должным образом. Я предполагаю, что, не вдаваясь в подробности кода, либо по умолчанию используется массив, либо данные для по какой-то причине был закодирован как массив, когда это было необязательно, если у меня будет время в течение недели, я посмотрю и посмотрю, смогу ли я определить точное место, где возникает проблема, и обновлю свой ответ :) - person Mostafa Berg; 17.01.2018