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

о, что я еще не выяснил или не смог найти в Интернете на данный момент.

Есть ли способ добавить дополнительные поля в структуру, содержащую декодируемый протокол, в котором нет данных JSON?

Например, для простоты, скажем, у меня есть массив объектов JSON, структурированных как таковые

{"name": "name1", "url": "www.google.com/randomImage"}

но, скажем, я хочу добавить переменную UIImage к этой структуре, содержащей декодируемые, такие как

struct Example1: Decodable {
    var name: String?
    var url: String?
    var urlImage: UIImage? //To add later
}

Есть ли способ реализовать декодируемый протокол, чтобы получить имя и URL-адрес из JSON, но позвольте мне добавить UIImage позже?

 andyvn2207 сент. 2017 г., 23:09
@Rob: я так не думаю - так какUIImage неDecodable он даже не синтезирует соответствие протокола

Ответы на вопрос(2)

ИсключатьurlImage вы должны вручную соответствоватьDecodable вместо того, чтобы позволить синтезировать его требования:

struct Example1 : Decodable { //(types should be capitalized)
    var name: String?
    var url: URL? //try the `URL` type! it's codable and much better than `String` for storing URLs
    var urlImage: UIImage? = nil //not decoded

    private enum CodingKeys: String, CodingKey { case name, url } //this is usually synthesized, but we have to define it ourselves to exclude `urlImage`
}

По какой-то причине это работает, только если вы добавляете= nil вurlImageхотя значение по умолчаниюnil обычно предполагается для необязательных свойств. Если вы хотите предоставить значение дляurlImage при инициализации, а не при использовании= nilВы также можете вручную определить инициализатор:

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        url = try container.decode(URL.self, forKey: .url)
        urlImage = //whatever you want!
    }
 Hamish26 мая 2018 г., 18:57
И это теперь исправлено в Swift 4.1, вы можете опустить= nil :)
 Rykuno07 сент. 2017 г., 23:40
Огромное спасибо! Это довольно странно, и это было моей проблемой, я полагаю. Я назначал значение nil моей переменной, исключенной из свойства json, и продолжал выдавать ошибки.
 andyvn2207 сент. 2017 г., 23:21
@ Хамиш: аккуратный трюк!
 Itai Ferber08 сент. 2017 г., 02:32
Необходимо явно назначитьnil это ошибка в поведении (надзор, на самом деле), которую я сейчас исправляю. Это не должно быть необходимым в будущем.
 Hamish07 сент. 2017 г., 23:15
Компилятор может на самом деле синтезироватьinit(from:) для тебя. Вам просто нужно сказатьvar urlImage: UIImage? = nil чтобы удовлетворить его потребность в значении по умолчанию для свойства, не перечисленного вCodingKeys (почему он не принимает неявное значение по умолчаниюnil Я не слишком уверен).

я бы сделал urlImage ленивым var. Таким образом, вам не нужно беспокоиться об изменении ключей кодирования. Все, что вам нужно сделать, это написать свой геттер, вот так ...

struct Example1 : Decodable {

    var name : String?
    var url  : URL?    // Better than String

    lazy var urlImage: UIImage? = {
        // Put your image-loading code here using 'url'
    }()
}
 Sergnsk17 дек. 2018 г., 09:43
Проблема с этим решением заключается в том, что он работает только для вар. Если я хочу сделать что-то вродеlet example = ... Я больше не могу получить доступ к urlImage, потому что пример объекта теперь неизменен.
 MarqueIV19 дек. 2018 г., 06:57
В его примере было сказано «добавить позже», поэтому я написал это так, но если вы хотите, чтобы это воспринималось как «пусть», по крайней мере из внешнего мира, просто используйтеprivate(set) lazy var lazyTest: Int = { ... }

Ваш ответ на вопрос