Home > Back-end >  swift get element from array of dictionary
swift get element from array of dictionary

Time:08-26

I have this an array of dictionary composed by this model

struct CreditCardGroupTransaction: Identifiable {
    let id: String = UUID().uuidString
    let titleCardGroup: String
    let crediCard: [CreditCardModel]
}

struct CreditCardModel: Identifiable, Codable {
    let id: Int
    var isDefault: Bool
    var cardName: String
    var accountingPeriodStart: Int
    var accountingPeriodEnd: Int
    var accountingDay: Int
    var creditCardType: CreditCardType
    var cardColorRed: Double
    var cardColorBlu: Double
    var cardColorGreen: Double
}

and I need to get the element where from the array of crediCard isDefault = true

so I try in this way but because of option value it crashed

my instance of the element I want to update

@Published var selectedCard: CreditCardModel = CreditCardModel(id: 0, isDefault: false, cardName: "", accountingPeriodStart: 0, accountingPeriodEnd: 0, accountingDay: 0, creditCardType: .credit, cardColorRed: 0, cardColorBlu: 0, cardColorGreen: 0)

and here my try

for element in allCreditCards {
        selectedCard = element.crediCard.first(where: { $0.isDefault == true })!
}

but compiler say:

Value of optional type 'CreditCardModel?' must be unwrapped to a value of type 'CreditCardModel so I add the ! at the end

where allCreditCards is the array of CreditCardGroupTransaction

and it crashes

CodePudding user response:

An error like "Value of optional type 'CreditCardModel?' must be unwrapped", does not mean simply add a force unwrap ! at the end.

You should consider what happens if the value is nil.

Typically that's done by saying

if let thing = something { ... do something with thing ... }

In your case that would be like:

    if let selected = element.crediCard.first(where: { $0.isDefault == true }) {
       selectedCard = selected
    }

Or by making selectedCard an optional, to indicate the possibility that there may be no selected card.

The problem with modelling your domain by having an array of CreditCardModel's and hoping that exactly one of them will have an isDefault = true value is that it's possible that: there is more than one card with isDefault = true, and it's possible that there is no entries in the array, or that there are no cards with isDefault = true.

You can check and test for these situations, and have your program do sensible things if they occur, or:

You can eliminate these bugs from your program by designing your type carefully like, if you want to model the idea that there must be exactly one default card in a GroupTransaction:

Remove the 'isDefault' bool from CreditCardModel, then:

struct GroupTransaction: Identifiable {
    let id: String = UUID().uuidString
    let title: String

    let defaultCard: CreditCard
    let otherCards: [CreditCard]
}

Now it's not possibly to have 0, or more than one default card in a GroupTransaction, and you don't have to write code that worries about this situation, i.e. you can't construct a GroupTransaction that is not valid.

  • Related