简体   繁体   English

在 swift 中使用“默认值”创建非可选 Codable 的最佳方法

[英]Best approach to create Non-optional Codable with `default values` in swift

I know the basic concept of class and struct but which is more effective to create models for API to fetch data and tell me with pros and cons.我知道classstruct的基本概念,但它更有效地为 API 创建模型以获取数据并告诉我优缺点。

Previously i don't use optional for models.以前我不使用可选的模型。 Instead i give it some value.相反,我给它一些价值。 ie IE

class CompanyInfo : Codable {
    var NameEn : String = ""
    var CityEn : String = ""
    var Website : String = ""
    var Email : String = ""
    var Phone : String = ""
    var Fax : String = ""
}

but when it get some null value from API.但是当它从 API 获得一些null值时。 ie "Fax": null then App get crashed because it can't parse data with following line"Fax": null然后应用程序崩溃,因为它无法使用以下行解析数据

let data = try JSONDecoder().decode(dataModel.self, from: dataSet)

what is the best way to deffine a model so i don't need to unwrap optional or give it default value.定义 model 的最佳方法是什么,所以我不需要解开可选或给它默认值。

You can implement a custom decoder with default values:您可以使用默认值实现自定义解码器:

class CompanyInfo : Codable {
    var NameEn: String
    var CityEn: String
    var Website: String
    var Email: String
    var Phone: String
    var Fax: String
    
    required init(from decoder: Decoder) throws {
        do {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.NameEn = try container.decodeIfPresent(String.self, forKey: .NameEn) ?? "Default"
            self.CityEn = try container.decodeIfPresent(String.self, forKey: .CityEn) ?? "Default"
            self.Website = try container.decodeIfPresent(String.self, forKey: .Website) ?? "Default"
            self.Email = try container.decodeIfPresent(String.self, forKey: .Email) ?? "Default"
            self.Phone = try container.decodeIfPresent(String.self, forKey: .Phone) ?? "Default"
            self.Fax = try container.decodeIfPresent(String.self, forKey: .Fax) ?? "Default"
        }
    }
}

Unrelated to question, but important Note:与问题无关,但很重要注意:

In Swift, only Types names should start with a capital letter.在 Swift 中,只有Types名称应该以大写字母开头。 If you continue naming variables like this, you will have a serious refactoring issue one day if you decide to use CoreData or working with other Swift developers.如果你继续这样命名变量,如果你决定使用CoreData或与其他 Swift 开发人员合作,那么有一天你会遇到严重的重构问题。

Any future colleague will thank you if the data model reflects the JSON response of the API ("Don't make me think").如果数据 model 反映了 API 的 JSON 响应(“不要让我思考”),任何未来的同事都会感谢您。 Furthermore, for now you don't want to have optional values - in 3 weeks you perhaps need them - then you have some ugly checks:此外,现在你不希望有可选值——在 3 周内你可能需要它们——然后你有一些丑陋的检查:

if companyInfo.fax == "default" {
   // Hey it's the default value but this indicates that the value is optional and nil
}

However, it's doable:但是,这是可行的:

https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types

By the way - also have reading on Swift naming conventions regarding property names.顺便说一句 - 还阅读有关属性名称的 Swift 命名约定。

https://swift.org/documentation/api-design-guidelines/ https://swift.org/documentation/api-design-guidelines/

There is no such answer for more efficient use of class or struct .对于更有效地使用classstruct ,没有这样的答案。 that's depends on your need, app's demand and it's coding structure.这取决于您的需求、应用程序的需求及其编码结构。

If you have to deal with the optionals at runtime this can be the best approach according to me.如果您必须在运行时处理选项,这可能是我认为的最佳方法。

I would prefer to use struct on this我宁愿在这个上使用struct

struct YOUR_MODEL_NAME : Codable {

    var NameEn : String?
    var CityEn : String?
    var Website : String?
    var Email : String?
    var Phone : String?
    var Fax : String?

    enum CodingKeys: String, CodingKey {
        case NameEn = "YOUR_KEY_FOR_NameEn"
        case CityEn = "YOUR_KEY_FOR_CityEn"
        case Website = "YOUR_KEY_FOR_Website"
        case Email = "YOUR_KEY_FOR_Email"
        case Phone = "YOUR_KEY_FOR_Phone"
        case Fax = "YOUR_KEY_FOR_Fax"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        NameEn = try values.decodeIfPresent(String.self, forKey: .NameEn)
        CityEn = try values.decodeIfPresent(String.self, forKey: .CityEn)
        Website = try values.decodeIfPresent(String.self, forKey: .Website)
        Email = try values.decodeIfPresent(String.self, forKey: .Email)
        Phone = try values.decodeIfPresent(String.self, forKey: .Phone)
        Fax = try values.decodeIfPresent(String.self, forKey: .Fax)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否可以动态创建swift协议的可选和非可选版本? - Is it possible to create an optional and non-optional version of a swift protocol dynamically? 如何在 Swift 中处理 NSUserDefaults 中的非可选值 - How to deal with non-optional values in NSUserDefaults in Swift Swift和最佳用例中可选和非可选函数参数之间的语义 - Semantics between optional and non-optional function parameters in Swift and best use cases 在Swift中使用.Success枚举返回非可选 - Return non-optional with .Success enum in Swift 迅速:推迟非可选对象的初始化 - swift: defer non-optional object initialization 用非可选值创建一个常量元组,然后与另一个具有可选值的元组进行比较 - Create a constant tuple with Non-optional values and compare with another tuple which has optional values 快速使用非可选对象将其视为可选 - Using non-optional object while swift consider it optional Swift中的非可选类型不应该包含可选吗? - Shouldn't an optional be inclusive to a non-optional type in Swift? 有没有办法强制Swift中的TextField中的文本是非可选的? - Is there a way to force the text in a TextField in Swift to be non-optional? Swift比较Strings选项与非选项 - Swift comparing Strings optionals vs non-optional
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM