NSManagedObject Better Integrated w/ Beta 5

Sounds like NSManagedObject now conforms to ObservableObject and there's a new property wrapper @FetchRequest that can "can drive views from the results of a fetch request".


Just digging in now but curious if anyone gets a working sample before I do.

Replies

Ok, trying to figure out how this is supposed to work (no docs or sample yet AFAICT) and not having a ton of luck yet. Anyone else?

I got this to work in a simple demo.


Scene Delegate:


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        let container = (UIApplication.shared.delegate as? AppDelegate)!.persistentContainer
        let context = container.viewContext
        
        if let windowScene = scene as? UIWindowScene {
            let rootView = ContentView().environment(\.managedObjectContext, context)

            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: rootView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }


Root View:


struct ContentView: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(fetchRequest: fetchRequest(), animation: nil) var newsItems: FetchedResults<News>
    
    var body: some View {
        NavigationView {
            List(self.newsItems, id: \.self) { newsItem in
                Text(newsItem.title!)
            }
            .navigationBarItems(trailing:
                Button(action: {
                    self.insertNews()
                }) {
                    Image(systemName: "plus.circle")
                }
            )
        }
    }
    
    func insertNews() {
        let news = News(context: managedObjectContext)
        news.title = "Test"
    }
    
    static func fetchRequest() -> NSFetchRequest<News> {
        let request: NSFetchRequest<News> = News.fetchRequest()
        request.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)]
        
        return request
    }
}

Not super pretty yet but it does work!

This is awesome…thanks for the code snippet!


My guess is with a SwiftUI "List", this is still going to load all of the matching ManagedObjects into memory with a single fetch request (versus what UIKit can do with does with faulting, using an NSFetchedResultsController and UITableView's dataSource methods).

Based on the stack trace, it looks like @FetchRequest is wrapping NSFetchedResultsController but I haven't tested if it loads everything at once or if the faults work as previously.

From the tests I've made, it seems to load only the displayed items.

Thanks for providing this demo, works with my case, too.


But, is there a way to include another view from a different file instead of the

Text(newsItem.title!)

I used it before with Bindings, but did not succeed with the

@FetchRequest(fetchRequest: fetchRequest(), animation: nil) var newsItems: FetchedResults


Any idea or demo, too?

From the Core Data template (XCode 11), if I change the Event object to update the timestamp property from the detail view, the list in the master view is refreshed (and correctly display the event updated timestamp), but the visible content in the detail view is not (the Text displaying the formatted timestamp). Do you know why?