簡體   English   中英

在 swift 中使用“默認值”創建非可選 Codable 的最佳方法

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

我知道classstruct的基本概念,但它更有效地為 API 創建模型以獲取數據並告訴我優缺點。

以前我不使用可選的模型。 相反,我給它一些價值。 IE

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

但是當它從 API 獲得一些null值時。 "Fax": null然后應用程序崩潰,因為它無法使用以下行解析數據

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

定義 model 的最佳方法是什么,所以我不需要解開可選或給它默認值。

您可以使用默認值實現自定義解碼器:

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 中,只有Types名稱應該以大寫字母開頭。 如果你繼續這樣命名變量,如果你決定使用CoreData或與其他 Swift 開發人員合作,那么有一天你會遇到嚴重的重構問題。

如果數據 model 反映了 API 的 JSON 響應(“不要讓我思考”),任何未來的同事都會感謝您。 此外,現在你不希望有可選值——在 3 周內你可能需要它們——然后你有一些丑陋的檢查:

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

但是,這是可行的:

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

順便說一句 - 還閱讀有關屬性名稱的 Swift 命名約定。

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

對於更有效地使用classstruct ,沒有這樣的答案。 這取決於您的需求、應用程序的需求及其編碼結構。

如果您必須在運行時處理選項,這可能是我認為的最佳方法。

我寧願在這個上使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM