致命错误:在字典中发现“AnyHashable”类型的重复键

问题描述 投票:0回答:1

当用户在 AddProductionView 中单击

Save
时,我收到以下致命错误。

致命错误:在字典中发现“AnyHashable”类型的重复键。 这通常意味着该类型违反了 Hashable 的要求,或者 这样的字典的成员在插入后发生了变异。

据我所知,SwiftData 自动使其模型符合 Hashable,所以这应该不是问题。

我认为这与选择器有关,但我怎么也看不出是什么。

单击“保存”时,大约 75% 的情况下会出现此错误。

任何帮助将不胜感激......

这是我的代码:

import SwiftUI
import SwiftData

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .modelContainer(for: Character.self, isAutosaveEnabled: false)
        }
    }
}

@Model
final class Character {
    var name: String
    var production: Production
    var myCharacter: Bool
    
    init(name: String, production: Production, myCharacter: Bool = false) {
        self.name = name
        self.production = production
        self.myCharacter = myCharacter
    }
}

@Model
final class Production {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

struct ContentView: View {
    @State private var showingSheet = false
    var body: some View {
        Button("Add", systemImage: "plus") {
            showingSheet.toggle()
        }
        .sheet(isPresented: $showingSheet) {
            AddProductionView()
        }
    }
}

struct AddProductionView: View {
    @Environment(\.dismiss) private var dismiss
    @Environment(\.modelContext) var modelContext
    
    @State var production = Production(name: "")
    @Query var characters: [Character]
    
    @State private var characterName: String = ""
    @State private var selectedCharacter: Character?
    
    var filteredCharacters: [Character] {
        characters.filter { $0.production == production }
    }
    
    var body: some View {
        NavigationStack {
            Form {
                Section("Details") {
                    TextField("Title", text: $production.name)
                }
                Section("Characters") {
                    List(filteredCharacters) { character in
                        Text(character.name)
                    }
                    HStack {
                        TextField("Character", text: $characterName)
                        Button("Add") {
                            let newCharacter = Character(name: characterName, production: production)
                            modelContext.insert(newCharacter)
                            characterName = ""
                        }
                        .disabled(characterName.isEmpty)
                    }
                    if !filteredCharacters.isEmpty {
                        Picker("Select your role", selection: $selectedCharacter) {
                            Text("Select")
                                .tag(nil as Character?)
                            ForEach(filteredCharacters) { character in
                                Text(character.name)
                                    .tag(character as Character?)
                            }
                        }
                        .pickerStyle(.menu)
                    }
                }
            }
            .toolbar {
                Button("Save") { //Fatal error: Duplicate keys of type 'AnyHashable' 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.
                    if let selectedCharacter = selectedCharacter {
                        selectedCharacter.myCharacter = true
                    }
                    modelContext.insert(production)
                    do {
                        try modelContext.save()
                    } catch {
                        print("Failed to save context: \(error)")
                    }
                    dismiss()
                }
                .disabled(production.name.isEmpty || selectedCharacter == nil)
            }
        }
    }
}
swift swiftui swiftdata
1个回答
0
投票

我不确定崩溃的原因,因为(据我所知)不知道如何计算 PersistentModel 对象的哈希值,但我相信这与如何以及何时重新计算哈希值有关production 属性和/或

characters
属性中的元素可能会导致崩溃,因为某些内容以错误的顺序更新。
处理创建两种不同类型模型的视图,然后处理它们之间的关系也可能非常棘手。因此,当我测试它时,下面的解决方案没有生成任何崩溃,它通过不使用任何类型的模型属性来简化整个解决方案,而是使用模型属性的属性,并在“保存”时以受控方式创建和插入所有新模型“按钮被按下。

struct AddProductionView: View { @Environment(\.dismiss) private var dismiss @Environment(\.modelContext) var modelContext @State private var production = "" @State private var productionID: PersistentIdentifier? @State private var characters: [String] = [] @State private var characterName: String = "" @State private var selectedCharacter: String? var body: some View { NavigationStack { Form { Section("Details") { TextField("Title", text: $production) } Section("Characters") { List(characters, id: \.self) { character in Text(character) } HStack { TextField("Character", text: $characterName) Button("Add") { characters.append(characterName) characterName = "" } .disabled(characterName.isEmpty || characters.contains(characterName)) } if !characters.isEmpty { Picker("Select your role", selection: $selectedCharacter) { Text("Select") .tag(nil as String?) ForEach(characters, id: \.self) { character in Text(character) .tag(character as String?) } } .pickerStyle(.menu) } } } .toolbar { Button("Save") { let production = Production(name: production) modelContext.insert(production) for name in characters { let character = Character(name: name, production: production) if let selectedCharacter, name == selectedCharacter { character.myCharacter = true } } do { try modelContext.save() } catch { print("Failed to save context: \(error)") } dismiss() } .disabled(production.isEmpty || selectedCharacter == nil) } } } }

	
© www.soinside.com 2019 - 2024. All rights reserved.