Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
857 views
in Technique[技术] by (71.8m points)

core data - SwiftUI connect CoreDate to settings window (macOS)

I recently added a settings pane to my app, and tried to connect it to core data to let the users mange their api and url settings.
But unfortunately when I launch my app and open the settings pane I alway get a bunch of errors telling me that core data is not connected correctly or something like that. - error messages below
-----------------------------------------

This is my App.swift file where I added the settings pane.

@main
struct RandomAppName: App {
    
    let persistenceController = PersistenceController.shared
    @State private var filter = 1
    
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(.managedObjectContext, persistenceController.container.viewContext)
         
        }
       .commands { // some command features }
                
        
        
        #if os(macOS)
        
                Settings {
                    SettingsPane()
                        .environment(.managedObjectContext, persistenceController.container.viewContext)
                     }
        
                #endif
        
        
        }
        }

The settings pane itself contains a tabview with serval subviews.
Here some code snippets.

import SwiftUI

struct SettingsPane: View {
    
    @Environment(.managedObjectContext) private var viewContext
    @State private var id : Int = 3

 var body: some View {

// some content stuff //

  if id == 1 || id == 0 {  ApiView().environment(.managedObjectContext, PersistenceController.preview.container.viewContext)  }

// some content stuff //

}
}

And some of the actual Api settings view

import SwiftUI

struct ApiView: View {

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: APIMaster.timestamp, ascending: true)],
        animation: .default)
    private var content: FetchedResults<APIMaster>

   var body: some View {

    // some content stuff //

        VStack{

          ScrollView{
          ForEach(content,  id: .self) { content in

            HStack{
             Image(systemName: "xserve")
             Text(content.hostName)
             }

            }}

    // some content stuff //
 

} }


struct ApiView_Previews: PreviewProvider {
    static var previews: some View {
        ApiView().environment(.managedObjectContext, PersistenceController.preview.container.viewContext)
    }
}


everything had been working fine until I implemented the core data part.
I already tested the ForEach loop with the core data connection in the app view and there it works perfectly fine.

The error message is:

2021-01-09 21:28:11.348566+0100 RandomAppName[71835:2714021] [error] warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'APIMaster' so +entity is unable to disambiguate. CoreData: warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'APIMaster' so +entity is unable to disambiguate.
2021-01-09 21:28:11.348698+0100 RandomAppName[71835:2714021] [error] warning: 'APIMaster' (0x600003128000) from NSManagedObjectModel (0x600002530230) claims 'APIMaster'. CoreData: warning: 'APIMaster' (0x600003128000) from NSManagedObjectModel (0x600002530230) claims 'APIMaster'.

I hope somebody can help me with this specific problem.

Here is what the settings pane looks like. (I also tried the "main" entity)

enter image description here

question from:https://stackoverflow.com/questions/65647616/swiftui-connect-coredate-to-settings-window-macos

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I finally found a very easy way to solve my problem.
The following code works perfect for me in Xcode 12.3.
To access the PersistenceController.shared we need to connect our view to the "main" PersistenceController.shared, which is called in the App file.

@main
struct RandomAppName: App {

let persistenceController = PersistenceController.shared
@State private var filter = 1


var body: some Scene {
    WindowGroup {
        ContentView()
            .environment(.managedObjectContext, persistenceController.container.viewContext)
     
    }
   .commands { // some command features }
            
    
    
    #if os(macOS)
    
            Settings {
                SettingsPane(viewContext: persistenceController.container.viewContext)
                    .environment(.managedObjectContext, persistenceController.container.viewContext)
                 }
    
            #endif
    
    
    }
    }

In the settings window we ask for the Persistence like this:

import SwiftUI

struct SettingsPane: View {
    
   let viewContext : NSManagedObjectContext // ask for the persistence

    @State private var id : Int = 3

 var body: some View {

// some content stuff //

  if id == 1 || id == 0 {  ApiView(viewContext: viewContext)  } // pass the persistence to the subview

// some content stuff //

}
}

And Finale in the subview:

import SwiftUI

struct ApiView: View {

 let viewContext : NSManagedObjectContext // ask for the persistence

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: APIMaster.timestamp, ascending: true)],
        animation: .default)
    private var content: FetchedResults<APIMaster>

   var body: some View {

    // some content stuff //

        VStack{

          ScrollView{
          ForEach(content,  id: .self) { content in

            HStack{
             Image(systemName: "xserve")
             Text(content.hostName)
             }

            }}

    // some content stuff //
 



  } }
    
   // I just uncomment the PreviewProvider because it's not necessary for me 
   // struct ApiView_Previews: PreviewProvider {
   //     static var previews: some View {
   //          ApiView()
   //     }
   //  }

This works fine for me (I don't know if this is the official way)
Hope I could help someone who has the same problem.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...