Ни один из кандидатов 'decodeIfPresent' не создает ожидаемый контекстный тип результата '[ModelMemberSubCategory]!' - PullRequest
0 голосов
/ 23 октября 2018

У меня есть две собственные модели структуры, использующие Codable.Один - ModelMemberCategory, а другой - ModelMemberSubCategory, который является потомком ModelMemberCategory.Вот фрагмент кода:

ModelMemberCategory

struct ModelMemberCategory: Encodable {

    var catId : Int!
    var catName : String!
    var fields : [ModelMemberSubCategory]!

    //For Codable

    enum CodingKeys: String, CodingKey {
        case catId = "cat_id"
        case catName = "cat_name"
        case fields = "fields"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        catId = try values.decodeIfPresent(Int.self, forKey: .catId)
        catName = try values.decodeIfPresent(String.self, forKey: .catName)
        fields = try values.decodeIfPresent([ModelMemberSubCategory].self, forKey: .fields) // This line throws error on Xcode 9.4.1 but not on Xcode 9.2
    } 
}

ModelMemberSubCategory

struct ModelMemberSubCategory: Encodable{

    var fieldCategory : String!
    var fieldCode : String!
    var fieldDatatype : String!
    var fieldId : Int!
    var fieldName : String!
    var fieldType : String!
    var fieldValue : String!
    var fieldValuetype : String!
    var fieldVisible : String!


    //Codable
    enum CodingKeys: String, CodingKey {
        case fieldCategory = "field_category"
        case fieldCode = "field_code"
        case fieldDatatype = "field_datatype"
        case fieldId = "field_id"
        case fieldName = "field_name"
        case fieldValue = "field_value"
        case fieldValuetype = "field_valuetype"
        case fieldVisible = "field_visible"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        fieldCategory = try values.decodeIfPresent(String.self, forKey: .fieldCategory)
        fieldCode = try values.decodeIfPresent(String.self, forKey: .fieldCode)
        fieldDatatype = try values.decodeIfPresent(String.self, forKey: .fieldDatatype)
        fieldId = try values.decodeIfPresent(Int.self, forKey: .fieldId)
        fieldName = try values.decodeIfPresent(String.self, forKey: .fieldName)
        fieldValue = try values.decodeIfPresent(String.self, forKey: .fieldValue)
        fieldValuetype = try values.decodeIfPresent(String.self, forKey: .fieldValuetype)
        fieldVisible = try values.decodeIfPresent(String.self, forKey: .fieldVisible)
    }
}

Теперь проблема заключается в его построениив Xcode 9.2, но не в Xcode 9.4.1.В то время как я пытаюсь построить, используя 9.4.1, я получаю ошибку, подобную этой:

Нет кандидатов 'decodeIfPresent', создающих ожидаемый контекстный тип результата '[ModelMemberSubCategory]!'

на

fields = try values.decodeIfPresent([ModelMemberSubCategory].self, forKey: .fields) в ModelMemberCategory

Я не знаю, что Apple изменила в версии Xcode 9.4.1, но может кто-нибудь помочь мне преодолетьэта ошибка?

1 Ответ

0 голосов
/ 23 октября 2018

Вам нужно Decodable вместо Encodable.Decodable необходимо для представления внешнего объекта вашему типу

Изменение Encodable на Decodable исправляет ошибку.

Код создается в XCode 9.2, посколькув Swift 4.0 (<4.1) компилятор не проверяет, соответствуют ли ваши структуры Decodable или нет.Это было исправлено в Swift 4.1 (XCode 9.3+) с использованием <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md" rel="nofollow noreferrer"> Условного соответствия.
Подробнее об этом можно прочитать здесь.

Напримечание, в ModelMemberSubCategory, fieldType отсутствует.Я надеюсь, что это сделано намеренно.
Кроме того, decodeIfPresent возвращает Optional значения, но все переменные вашего экземпляра не являются необязательными.Если вы думаете, что некоторые переменные могут быть nil, вы должны сделать их необязательными, чтобы вы могли лучше обрабатывать nil-значения в вашем коде.

...