如何处理nil值变量

时间:2018-05-28 12:28:35

标签: null swift4 jsondecoder

我的模型如下。

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

在tableview单元格中显示时,我正在做的如下。

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

如果我有以下格式的数据

,现在应用程序崩溃了
[
    {
        "firstName" : "F 1",
        "lastName" : "L 1"
    },
    {
        "firstName" : "F 2"
    },
    {
        "lastName" : "L 3"
    }
]

该应用程序崩溃,称lastName为零

解决方案1 ​​

此检查的解决方案为零&然后显示名称,但我不想在运行时进行检查,因为 我必须检查所有变量(考虑到我有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个变量。

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

1 个答案:

答案 0 :(得分:0)

我建议使用以下两个选项之一:

  1. 将计算属性添加到结构中以确定显示名称。
  2. 手动解码,提供默认值。 (如果需要,还可以添加显示名称属性)
  3. 就个人而言,我喜欢选项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: ""