I hope I can make myself clear. I have two CoreData entities User
and SecretItem
. One User can hold an NSSet of SecrteItems. I set the relationship to Many
at the user with destination SecretItem
and to One
at SecretItem with destination User
.
I use a two column NavigationSplitView in my ContenView (macos app) performing the @FetchRequest only here, not in the Detail-View:
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: [SortDescriptor(\.name)])
private var users: FetchedResults<User>
@State private var selectedUserID: User.ID?
@State private var defaultUserID: User.ID?
var body: some View {
NavigationSplitView {
SidebarView(selection: selection)
} detail: {
if selection.wrappedValue != nil {
SecretDetailView(user: selectedUser)
} else {
Text("Please select a user")
}
}
}
private var selection: Binding<User.ID?> {
Binding(get: { selectedUserID ?? defaultUserID }, set: { selectedUserID = $0 })
}
private var selectedUser: User {
users.filter({ $0.id == selection.wrappedValue }).first! // <-- passed user to the @ObservedOject user in Detail-View
}
}
Everything works fine. The users are listed in the Sidebar-View. A selected user is passed to ObservedObject var user: User
in the Detail-View showing the secretItem details. When I try to add another secretItem the app crashes pointing to the Swift app-file with Thread 1: EXC_BREAKPOINT (code=1, subcode=0x19d0b56b4)
I don't know how to add a new secretItem to the NSSet of the selected User. Any guidance?
here is my Detail-View with the add-func:
struct SecretDetailView: View {
@Environment(\.managedObjectContext) var moc
@ObservedObject var user: User
var secretItems: [SecretItem] {
return user.secretItems
.filter {
searchText.isEmpty ? true : $0.userName.localizedCaseInsensitiveContains(searchText)
}
.sorted(using: sortOrder)
}
@State var searchText: String = ""
@State private var selection = Set<SecretItem.ID>()
@State var sortOrder: [KeyPathComparator<SecretItem>] = [
.init(\.userName, order: SortOrder.forward)
]
// ... View Body stuff
}
extension SecretDetailView {
// only to have somthing to work with!
private func addSecretItems() {
let usernames = ["quingflack23", "norton", "k-flex@hotmail.com", "kia-lokie@gmx.net", "san-silver", "quarks123", "user01", "wonder woman"]
let passwords = ["1Jhg&%5", "123password", "noFun$3", "/(zhgTrF", "QTZ121!", "Wonder123)(", "awesomePW"]
let chosenName = usernames.randomElement()!
let chosenPW = passwords.randomElement()!
Task { await addSecretItem(name: chosenName, pw: chosenPW)}
}
private func addSecretItem(name: String, pw: String) async {
await moc.perform {
let secretItem = SecretItem(context: moc)
secretItem.id = UUID()
secretItem.userName = "\(name)"
secretItem.password = "\(pw)"
secretItem.user = user // <-- here an error is thrown. I'm not sure if this is right, the SecretItem has an @NSManaged public var user: User created
user.addToSecretItems(secretItem) // <-- this also throws an error. I try to use the created func in the User class
}
try? moc.save()
}
}