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.