I tried to use the .deny deleteRule but it seems to have no effect.
The toolbar button adds an item with a relationship to a category to the context. Swiping on the category deletes the category even though an item is referencing the category. There is also no error thrown when saving the context. It is as if the deleteRule was not there.
For other deleteRules like .cascade, the provided sample code works as expected.
import SwiftUI
import SwiftData
@Model
class Category {
var name: String
@Relationship(deleteRule: .deny) var items: [Item] = []
init(name: String) {
self.name = name
}
}
@Model
class Item {
var name: String
var category: Category?
init(name: String, category: Category) {
self.name = name
self.category = category
}
}
struct DenyDeleteRule: View {
@Environment(\.modelContext) private var modelContext
@Query private var categories: [Category]
@Query private var items: [Item]
var body: some View {
List {
Section("Items") {
ForEach(items) { item in
Text(item.name)
}
}
Section("Categories") {
ForEach(categories) { category in
VStack(alignment: .leading) {
Text(category.name).bold()
ForEach(category.items) { item in
Text("• \(item.name)")
}
}
}
.onDelete(perform: deleteCategory)
}
}
.toolbar {
Button("Add Sample") {
let category = Category(name: "Sample")
let item = Item(name: "Test Item", category: category)
modelContext.insert(item)
}
}
}
func deleteCategory(at offsets: IndexSet) {
for index in offsets {
let category = categories[index]
modelContext.delete(category)
do {
try modelContext.save()
} catch {
print(error)
}
}
}
}
#Preview {
NavigationStack {
DenyDeleteRule()
}
.modelContainer(for: [Item.self, Category.self], inMemory: true)
}
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I have encountered the following error and reduced my code to the minimum necessary to reliably reproduce this error.
Fatal error: Duplicate keys of type 'AnyHashable2' 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.
It occurs when
instances of a swiftdata model are inserted (the error occurs reliably when inserting five or more instances. Fewer insertions seems to make the error either more rare or go away entirely) and
a Picker with .menu pickerStyle is present.
Any of the following changes prevents the error from occuring:
adding id = UUID() to the Item class
removing .tag(item) in the picker content
using any pickerStyle other than .menu
using an observable class instead of a swiftdata class
I would greatly appreciate if anyone knows what exactly is going on here.
Tested using
XCode Version 16.4 (16F6),
iPhone 16 Pro iOS 18.5 Simulator and
iPhone 15 Pro iOS 18.5 real device.
import SwiftUI
import SwiftData
@Model class Item {
var name: String
init(name: String) {
self.name = name
}
}
struct DuplicateKeysErrorView: View {
@Environment(\.modelContext) private var modelContext
@Query(sort: \Item.name) private var items: [Item]
@State var selection: Item? = nil
var body: some View {
List {
Picker("Picker", selection: $selection) {
Text("Nil").tag(nil as Item?)
ForEach(items) { item in
Text(item.name).tag(item)
}
}
.pickerStyle(.menu)
Button("Add 5 items") {
modelContext.insert(Item(name: UUID().uuidString))
modelContext.insert(Item(name: UUID().uuidString))
modelContext.insert(Item(name: UUID().uuidString))
modelContext.insert(Item(name: UUID().uuidString))
modelContext.insert(Item(name: UUID().uuidString))
}
}
.onAppear {
try! modelContext.delete(model: Item.self)
}
}
}
#Preview {
DuplicateKeysErrorView()
.modelContainer(for: Item.self)
}
I noticed that when using .searchable inside a NavigationStack thats inside a TabView, the searchbar briefly overlays the content before disappearing. After that, it is hidden and appears as expected when swiping down.
This only happens when the .searchable is inside the NavigationStack, there is at least one navigationTitle and the NavigationStack is inside a TabView.
Tested on simulator and real device.
I would appreciate any help.
Thanks!
struct FirstScreen: View {
var body: some View {
TabView {
Tab("Tab", systemImage: "heart") {
NavigationStack {
NavigationLink {
SecondScreen()
} label: {
Text("Go to second screen")
}
.navigationTitle("First Screen")
}
}
}
}
}
struct SecondScreen: View {
@State private var text: String = ""
var body: some View {
List {
Text("Some view that extends all the way to the top")
}
.searchable(text: $text)
.navigationTitle("Second Screen")
}
}