как обрабатывать переменные с нулевым значением - PullRequest
0 голосов
/ 28 мая 2018

У меня есть модель, как показано ниже.

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 переменных.

Есть ли другой альтернативный способ, где будет назначено значение по умолчаниюесли эта переменная отсутствует в веб-сервисе?

1 Ответ

0 голосов
/ 29 мая 2018

Я бы порекомендовал один из двух вариантов:

  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: ""
...