Ios 在swift中创建具有“默认值”的非可选可编码文件的最佳方法

Ios 在swift中创建具有“默认值”的非可选可编码文件的最佳方法,ios,swift,xcode,codable,decodable,Ios,Swift,Xcode,Codable,Decodable,我知道class和struct的基本概念,但哪种方法更有效地为API创建模型以获取数据,并告诉我优缺点 以前,我不为模型使用可选选项。相反,我赋予它一些价值。即 class CompanyInfo : Codable { var NameEn : String = "" var CityEn : String = "" var Website : String = "" var Email : String = "" var Phone : String

我知道
class
struct
的基本概念,但哪种方法更有效地为API创建模型以获取数据,并告诉我优缺点

以前,我不为模型使用可选选项。相反,我赋予它一些价值。即

class CompanyInfo : Codable {
    var NameEn : String = ""
    var CityEn : String = ""
    var Website : String = ""
    var Email : String = ""
    var Phone : String = ""
    var Fax : String = ""
}
但是当它从API获得一些
null
值时。ie
“Fax”:null
然后应用程序崩溃,因为它无法用以下行解析数据

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

解除模型精细化的最佳方法是什么,这样我就不需要展开可选对象或为其指定默认值

如果数据模型反映了API的JSON响应(“不要让我思考”),任何未来的同事都会感谢您。此外,现在你不想有可选值-在3周内你可能需要它们-然后你有一些丑陋的检查:

if companyInfo.fax == "default" {
   // Hey it's the default value but this indicates that the value is optional and nil
}
然而,这是可行的:

顺便说一句,还可以阅读有关财产名称的Swift命名约定


您可以使用默认值实现自定义解码器:

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"
        }
    }
}
与问题无关,但请注意:
在Swift中,只有
类型
名称应以大写字母开头。如果您继续这样命名变量,如果您决定使用
CoreData
或与其他Swift开发人员合作,有一天您将面临严重的重构问题。

要更有效地使用
结构
,没有这样的答案。这取决于您的需求、应用程序的需求以及它的编码结构

如果您必须在运行时处理选项,根据我的说法,这可能是最好的方法

我更愿意在这个问题上使用
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)
    }
}

您不能这样做。@wahab您可以使用“光泽”或任何其他库,我们不需要手动创建数据模型,只要给他们JSON,他们就会为我们创建它。如果您需要示例,请告诉我。您可以这样做,但是您必须实现
init(来自解码器:解码器)到处抛出
,以便在值不存在时分配默认值。始终从
struct
开始,并在需要时将其更改为
class
。您也可以查看一些相关信息。@MojtabaHosseini谢谢,我不知道
decodeIfPresent(uu2;:forKey:)
。这是离题的,但你最终不得不处理默认值,回避选项是不可能的:我迟来的答复是Psorry。我正在尝试您的解决方案,但我遇到了另一个问题,我应该为我的泛型类
数据
指定默认值吗?这完全是另一个问题。请随时联系我。你可以在这里对链接发表评论,这样我就可以检查我是否可以帮你。