Как я могу вызвать метод `didSet`, используя протокол `Codable`

Как я могу вызвать метод didSet, используя протокол Codable.

    class Sample: Codable{
        var text : String? {
            didSet {
                print("didSet") // do not call
                extended_text = "***" + text! + "***"
            }
        }
        var extended_text : String?
    }

    let sample_json = "{\"text\":\"sample text\"}"
    let decoder = JSONDecoder()
    let sample = try! decoder.decode(Sample.self, from: sample_json.data(using: .utf8)!)
    print(sample.text!)
    print(sample.extended_text ?? "") 

person Maiko Ohkawa    schedule 21.12.2017    source источник


Ответы (1)


Вместо использования didSet вы должны просто сделать extendedText вычисляемым свойством только для чтения. Обратите внимание, что в Swift принято использовать camelCase вместо snake_case при именовании ваших свойств:

struct Sample: Codable {
    let text: String
    var extendedText: String {
        return "***" + text + "***"
    }
}

let sampleJson = """
{"text":"sample text"}
"""

do {
    let sample = try JSONDecoder().decode(Sample.self, from: Data(sampleJson.utf8))
    print(sample.text)            // "sample text\n"
    print(sample.extendedText)    // "***sample text***\n"
} catch {
    print(error)
}

Альтернативой, если вашей целью является запуск метода при инициализации вашей структуры Codable, является написание собственного пользовательского декодера:

class Sample: Codable {
    let text: String
    required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        text = try container.decode(String.self)
        print("did set")
    }
}

let sampleJson = "{\"text\":\"sample text\"}"
let decoder = JSONDecoder()
do {
    let sample = try decoder.decode([String: Sample].self, from: Data(sampleJson.utf8))
    print(sample["text"]?.text ?? "")
} catch {
    print(error)
}

Это напечатает:

поставил

Образец текста

person Leo Dabus    schedule 21.12.2017
comment
Спасибо. Вы правы. Однако мой код является образцом. На самом деле обработка более сложная, и я думаю, что мне нужно сохранить преобразованный объект. Я сожалею, что не сделал это достаточно ясно. - person Maiko Ohkawa; 21.12.2017
comment
Спасибо. Я исправил представление, вводящее в заблуждение. - person Maiko Ohkawa; 21.12.2017
comment
@MaikoOhkawa обратите внимание, что это не имеет ничего общего с протоколом Codable. если вы установите свойство текста sample.text = "any text", оно вызовет didSet, но не при инициализации вашего class или struct - person Leo Dabus; 21.12.2017
comment
Я не знал, но не при инициализации вашего класса или структуры. Я понимаю. Мой вопрос прояснился. Я рассмотрю другую обработку. Спасибо большое. - person Maiko Ohkawa; 21.12.2017
comment
@MaikoOhkawa Что вы можете сделать, так это создать собственный инициализатор декодера и выполнить там все, что вам нужно. - person Leo Dabus; 21.12.2017