Hi! I have a strange error in my SwiftUI app and need a clue how to solve this issue. I work on a timetable like app where I hold the data in the App struct
@StateObject private var appData = VorlesungsHandler()
and the classes are defined as
public class VorlesungsHandler : ObservableObject {
let dayList : [Weekdays] = [.Montag, .Dienstag]
@Published var vorlesungen : [Vorlesung] = [ Vorlesung(…), … ]
…
}
and
class Vorlesung : Hashable, Equatable, Identifiable, ObservableObject {
@Published var subject: ModuleType
@Published var person : Personen
let vID = UUID()
…
}
The appData object is passed down to the views and subviews via
.environmentObject(appData)
and it seems to work well.
Now I face an error when I change the array „vorlesungen“ in Appdata via
func updateVorlesung(oldID : UUID?, newV : Vorlesung) {
if oldID == nil {
self.vorlesungen.append(newV)
return
}
for i in 0..<self.vorlesungen.count {
if self.vorlesungen[i].vID == oldID! {
self.vorlesungen.remove(at: i)
self.vorlesungen.append(newV)
break
}
}
}
The error message is
Fatal error: Duplicate keys of type 'Vorlesung' were found in a Dictionary.
This usually means either that the type violates Hashable's requirements, or that members of such a dictionary were mutated after insertion.
This error does not occur every time but 30 to 50% of the changes. In my tests I did also add
self.objectWillChange.send()
in front of all array-change commands but it does not help.
Any clue how to solve this issue?
I did post the same question on Swift Forum and got a solution:
Currently your hash and == are using completely different properties, which leads to conflict between them. Are two Vorlesung with the same subject but different vID equal to each other, or not? According to == they are equal, but according to hash they are not. We need to fix that
You need to decide what makes two Vorlesung the same, and use these properties in both == and hash. Usually in a struct it's all of the properties, and that's handled by the autogenerated implementation
so a change in my code did solve the issue:
static func == (lhs: Vorlesung, rhs: Vorlesung) -> Bool {
let result = lhs.subject.compare(rhs.subject) == .orderedSame
return result
}
func hash(into hasher: inout Hasher) {
hasher.combine(subject)
}