In SwiftUI how to pass Fetched object to DetailView in CoreData

48 views Asked by At

I'm new to SwiftUI and CoreData and I try to implement persistence with CoreData in my macos app. Now I stuck with managing to pass the selected item from the SidebarView to the DetailView within a NavigationSplitView. The non-persistent ObservableObject DataStore is replaced with the persistent UserDataModel holding the entities User and SecretItem.

How do I pass the selected User in the SidebarView to the SecretDetailView to show the the details of the selected user? Thanks!

my ContentView:

import SwiftUI

struct ContentView: View {

 @Environment(\.managedObjectContext) var moc

 @FetchRequest(sortDescriptors: [SortDescriptor(\.name)])
 private var users: FetchedResults<User>

 //@EnvironmentObject var dataStore: DataStore   <-- old non-persistante Datastore
 @State private var selectedUserID: User.ID?
 @State private var defaultUserID: User.ID?


 var body: some View {
    NavigationSplitView {
        SidebarView(selection: selection)
        
    } detail: {
        SecretDetailView(user: selectedUser)
    }
 }

 private var selection: Binding<User.ID?> {
    Binding(get: { selectedUserID ?? defaultUserID }, set: { selectedUserID = $0 })
 }

 private var selectedUser: Binding<User> {
    //$dataStore[selection.wrappedValue]
    ???                                       <-- here I'm struggling
 }

my SecretDetailView:

import SwiftUI

struct SecretDetailView: View {

 @Environment(\.managedObjectContext) var moc
 @FetchRequest(sortDescriptors: [SortDescriptor(\.userName)])

 var secretItem: FetchedResults<SecretItem>
 @Binding var user: User                      <-- the Binding used in ContentView

 @State var searchText: String = ""
 @State private var selection = Set<SecretItem.ID>()

 @State var sortOrder: [KeyPathComparator<SecretItem>] = [
    .init(\.userName, order: SortOrder.forward)
 ]

 var table: some View {
    Table(selection: $selection, sortOrder: $sortOrder) {
        TableColumn("User Name", value: \.userName)
 ...
 
 var body: some View {
    
    ZStack(alignment: .bottom) {
        
        table
            .searchable(text: $searchText)
            .navigationTitle(user.name!)
            //.navigationSubtitle("file: kpoph")
 ...
1

There are 1 answers

0
JFS On

Ok, after some further help and reading I found the answer myself.

In ContentView the user is passed to the SecretDetailView as follows:

private var selectedUser: User {
    users.filter({ $0.id == selection.wrappedValue }).first! 
}

But this is not enough and will still throw an error. Thanks to this answer Binding is not to be used for FetchRequest /NSManagedObject. In the SecretItemView ObservedObject is the right choice:

@ObservedObject var user: User

Hope I can help others with similar issues.