【问题标题】:how to handle the nil value variables如何处理 nil 值变量
【发布时间】:2018-11-07 01:17:26
【问题描述】:

我的模型如下。

struc Info: Decodable {
    var firstName: String?
    var lastName: String?
}

在表格视图单元格中显示时,我正在做的事情如下。

personName.text = "\(personArray[indexPath.row].firstName!) \(personArray[indexPath.row].lastName!)"

如果我有以下格式的数据,现在应用程序会崩溃

[
    {
        "firstName" : "F 1",
        "lastName" : "L 1"
    },
    {
        "firstName" : "F 2"
    },
    {
        "lastName" : "L 3"
    }
]

应用程序崩溃说 lastName 是 nil


解决方案 1

此检查的解决方案为 nil 然后显示名称,但是我不想在运行时进行检查,因为 我必须检查所有变量(考虑到我有25 个变量)。以下是我可以做的。

var firstName = ""
if (personArray[indexPath.row].firstName == nil) {
    firstName = ""
} else {
    firstName = personArray[indexPath.row].firstName!
}

var lastName = ""
if (personArray[indexPath.row].lastName == nil) {
    lastName = ""
} else {
    lastName = personArray[indexPath.row].lastName!
}

personName.text = "\(firstName) \(lastName)"

解决方案 2

我可以在模型本身中进行更新,如下所示。

struc Info: Decodable {
    var firstName: String?
    var lastName: String?

    var firstName2 : String? {
    get {
        if (self.firstName==nil) {
            return ""
        }
        return firstName
    }

    var lastName2 : String? {
    get {
        if (self.lastName==nil) {
            return ""
        }
        return lastName
    }
}

personName.text = "\(personArray[indexPath.row].firstName2!) \(personArray[indexPath.row].lastName2!)"

但是我也有这个问题。这样,我必须再次创建 N 个变量。

如果网络服务中缺少该变量,是否还有其他替代方法可以分配默认值?

【问题讨论】:

标签: null swift4 jsondecoder


【解决方案1】:

我会推荐以下两种选择之一:

  1. 将计算属性添加到结构以确定显示名称。
  2. 手动解码,提供默认值。 (如果需要,还可以添加显示名称属性)

就个人而言,我喜欢选项 1。我认为它最紧凑,也最容易维护。

选项 1 示例:

struct Info1: Decodable {
    var firstName: String?
    var lastName: String?

    var displayName: String {
        return [self.firstName, self.lastName]
            .compactMap { $0 } // Ignore 'nil'
            .joined(separator: " ") // Combine with a space
    }
}

print(Info1(firstName: "John", lastName: "Smith").displayName)
// Output: "John Smith"

print(Info1(firstName: "John", lastName: nil).displayName)
// Output: "John"

print(Info1(firstName: nil, lastName: "Smith").displayName)
// Output: "Smith"

print(Info1(firstName: nil, lastName: nil).displayName)
// Output: ""

选项 2 示例:

struct Info2: Decodable {
    var firstName: String
    var lastName: String

    enum CodingKeys: String, CodingKey {
        case firstName, lastName
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        self.firstName = try container.decodeIfPresent(String.self, forKey: .firstName) ?? ""
        self.lastName = try container.decodeIfPresent(String.self, forKey: .lastName) ?? ""
    }

    // Optional:
    var displayName: String {
        return [self.firstName, self.lastName]
            .compactMap { $0.isEmpty ? nil : $0 } // Ignore empty strings
            .joined(separator: " ") // Combine with a space
    }

    // TEST:
    init(from dict: [String: Any]) {
        let data = try! JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
        self = try! JSONDecoder().decode(Info2.self, from: data)
    }
}

print(Info2(from: ["firstName": "John", "lastName": "Smith"]).displayName)
// Output: "John Smith"

print(Info2(from: ["lastName": "Smith"]).displayName)
// Output: "Smith"

print(Info2(from: ["firstName": "John"]).displayName)
// Output: "John"

print(Info2(from: [String: Any]()).displayName)
// Output: ""

【讨论】:

  • 我提供了示例数据以供理解。但是我有内在的内在模型。我是否需要为所有变量枚举 CodingKeys、init(来自解码器:解码器)?我问是因为我只为 1 实现,而应用程序因其他变量而崩溃。我必须选择选项 2,因为 1 对于所有变量都不容易实现。
  • 不幸的是,Decodable(和Encodable)要么是全自动的,要么是全自动的。如果您选择我的选项 2,那么您需要为所有属性提供 CodingKeys 案例并将它们包含在 init(from: Decoder) 中。
  • 我不能选择选项 1,因为我必须创建 N 个变量。现在我对图像变量有问题,但明天我可能对另一个变量有问题。所以我觉得选项 2 更好……对于选项 1,问题是我只有在崩溃时才能修复,否则我不会。
  • 这两个选项都有优点和缺点。使用您认为对您的应用程序更好或更容易的任何方法。选项 2 的坏处是您需要手动解码 JSON Decoder 中的每个值。
  • 是的。选项 2 有更多的工作,但好的一点是我正在使用 json4swift.com,他正在给我这些数据,所以我很安全 :)。 Option 1 最糟糕的一点是如果发生崩溃我们可以实现。如果没有崩溃,我们不知道哪个变量会保存 nil 数据。
猜你喜欢
  • 1970-01-01
  • 2016-04-24
  • 2015-09-05
  • 2012-05-12
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
  • 2023-01-13
  • 2011-10-13
相关资源
最近更新 更多