Лучший подход к созданию необязательного Codable со значениями по умолчанию в swift - PullRequest
2 голосов
/ 31 октября 2019

Я знаю основную концепцию class и struct, но которая более эффективна для создания моделей для API, чтобы извлекать данные и рассказывать мне о плюсах и минусах.

Ранее я не использовал опционально для моделей. Вместо этого я придаю этому значение. то есть

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

, но когда он получает какое-то значение null от API. т. е. "Fax": null, затем приложение аварийно завершает работу, потому что оно не может проанализировать данные следующей строкой

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

, что является лучшим способом определения модели, поэтому мне не нужно разворачивать опционально или задавать значение по умолчанию,

Ответы [ 3 ]

3 голосов
/ 31 октября 2019

Вы можете реализовать пользовательский декодер со значениями по умолчанию:

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.

0 голосов
/ 31 октября 2019

Нет такого ответа для более эффективного использования class или struct. это зависит от ваших потребностей, требований приложения и его структуры кодирования.

Если вам приходится иметь дело с опциями во время выполнения, это может быть лучшим подходом, по моему мнению.

Я бы предпочел использовать 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)
    }
}
0 голосов
/ 31 октября 2019

Любой будущий коллега поблагодарит вас, если модель данных будет отражать JSON-ответ API («Не заставляйте меня думать»). Кроме того, сейчас вы не хотите иметь дополнительные значения - через 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/

...