I've written some code but its not working as expected. I have the following code: My Contend View File:
import SwiftUI
struct ContentView: View {
@State var liste: [Can] = [Can()]
var body: some View {
Button {
liste[0].nested.change()
} label: {
Text("\(liste[0].nested.property)")
}
}
}
and an other file:
import SwiftUI
struct Can: Identifiable, Equatable, Codable, Hashable {
static func == (lhs: Can, rhs: Can) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
// Jedes Item
let id = UUID()
var nested = nestedThingies()
struct nestedThingies: Codable {
var property = 15
mutating func change(){
property -= 1
}
}
}
What I would expect from this code is that each time you press the button in ContentView
, the value of the nested.property
of the first item in the Array liste
gets 1 lower (property -= 1
).
What's Really Happening:
The function change()
gets called, but the value of property
only changes from 15 to 14 no Mather how often you press that button.
I've tested that code also in a empty Project, and it did the same strange thing...
Can someone explain that behavior to me? Thanks, Boothosh
CodePudding user response:
The issue is your implementation of Equatable
. You're telling the system that the elements are equal if their id
properties match. But, that's not true -- they are distinctly different if their nested
values change.
SwiftUI is taking your word for the fact that the elements are the same and doesn't update the UI. I'm not sure why it gets the first update right, but it definitely doesn't get the subsequent ones right. To make matters even more strange, if you print the property
value after it changes, it prints down to 13
, even though the UI stops updating at 14
. My theory is that the erroneous Equatable
function (==
) is interfering with the @State
storage that the system is doing.
If you update your ==
function to reflect the changed nested
value, it works as expected:
struct Can: Identifiable, Equatable, Codable, Hashable {
static func == (lhs: Can, rhs: Can) -> Bool {
lhs.id == rhs.id && lhs.nested.property == rhs.nested.property
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
// Jedes Item
var id = UUID()
var nested = nestedThingies()
struct nestedThingies: Codable {
var property = 15
mutating func change(){
property -= 1
}
}
}