Manual Core Data Requests in SwiftUI - core-data

Given that #FetchRequest does not support dynamic predicates (eg, I could not update the "month" in a calendar and re-query for the events I have scheduled in that month), I am trying to get a manual request to work.
The #FetchRequest already works if I don't try to make a dynamic predicate, so I assume the core data is configured to work correctly.
In my SceneDelegate I have:
guard let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext else {
fatalError("Unable to read managed object context.")
}
let contentView = ContentView().environment(\.managedObjectContext, context)
and in my AppDelegate:
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Transactions")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
If I try doing a manual request in my ContentView like:
let employeesFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Employees")
do {
let employees = try managedObjectContext.fetch(employeesFetch) as! [Employees]
} catch {
fatalError("Failed to fetch employees: \(error)")
}
This fails because `Exception NSException * "+entityForName: nil is not a legal NSPersistentStoreCoordinator for searching for entity name 'Employees'"
What configuration am I missing?

Related

How do I get SwiftUI to work with Core Data (after starting a project)?

I get this error when trying to get Xcode working with Core Data. Any help would be very appreciated.
Context in environment is not connected to a persistent store coordinator: <NSManagedObjectContext: 0x6000008a8820>
After commenting out all the other environments so that the persistence envinronment is only used in the top level, I still have the same error.
Here is the Apps Top-Level Swift File:
import SwiftUI
import CoreData
#main
struct Draw_DailyApp: App {
let persistenceController = PersistenceController.shared
#Environment(\.scenePhase) var scenePhase
#FetchRequest(entity: Drawing.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Drawing.img, ascending: true)])
var orders: FetchedResults<Drawing>
#State var showOrderSheet = false
// Creating a global environment and placing it into the environment
#ObservedObject var searchObjectController: SearchObjectController = SearchObjectController()
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.environmentObject(self.searchObjectController)
}
.onChange(of: scenePhase) { _ in
persistenceController.save()
}
}
}
and here is the file where persistent controller is used (Core Data xcdatamodeld has one Binary Data attribute called img)
Persistence.Swift
import CoreData
import UIKit
struct PersistenceController {
static let shared = PersistenceController()
func save() {
let context = container.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Show some error here
}
}
}
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
for _ in 0..<10 {
let newItem = Drawing(context: viewContext)
newItem.img = Data()
newItem.date = "02081999"
}
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
let container: NSPersistentContainer
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "DrawDaily")
if inMemory {
container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
}
PS: I didn't start this project with Core Data, I added it in later
Your #FetchRequest doesn't have a NSManagedObjectContext upon init. You are creating it with this line
let persistenceController = PersistenceController.shared
Your #FetchRequest has to move down into the ContentView for it to work.
This line has to be called
.environment(\.managedObjectContext, persistenceController.container.viewContext)
when initializing the View that contains the #FetchRequest

Core Data Widget with shared container conflict

The Scenario
I'm using Core Data inside my main app and my widget.
To share my Persistent Container I use this custom stack that targets both my app and my widget and its working fine
class CoreDataService {
static let shared = CoreDataService()
lazy var context: NSManagedObjectContext = persistentContainer.viewContext
lazy var persistentContainer: NSPersistentCloudKitContainer = {
let container = NSPersistentCloudKitContainer(name: "my.app.name")
let storeURL = URL.storeURL(for: "my.app.group", databaseName: "my.app.name")
let storeDescription = NSPersistentStoreDescription(url: storeURL)
container.persistentStoreDescriptions = [storeDescription]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext () {
let context = self.context
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
The Problem
But when I access my widget from the home and I tap it to go to the app, whenever I use #FetchRequest in my code I get this error
CoreData: error: +[Subject entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
And then my app crashes with this Stack Trace
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'executeFetchRequest:error: A fetch request must have an entity.'
Workaround
I partially solved it by changing this FetchRequest
#FetchRequest(entity: Subject.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Subject.name, ascending: true)]) private var subjects: FetchedResults<Subject>
to this one
#FetchRequest(fetchRequest: NSFetchRequest(entityName: "Subject")) private var subjects: FetchedResults<Subject>
But still don't know what I did wrong in the first place and why is this stupid change solving my problem and I would like to know if there is another way to solve it.

SwiftUI CloudKit Public Database with NSPersistentCloudKitContainer

Based on WWDC20 talk bellow:
https://developer.apple.com/videos/play/wwdc2020/10650/
The way to setup CloudKit Public Database with NSPersistentCloudKitContainer in "one line of code" is this:
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
description.setOption(true as NSNumber, forKey:NSPersistentStoreRemoteChangeNotificationPostOptionKey)
description.cloudKitContainerOptions?.databaseScope = .public
How would that be on the new SwiftUI Persistent.swift template?
I tried the code bellow but didn't work:
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
for _ in 0..<10 {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
}
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
let container: NSPersistentCloudKitContainer
//This doesnt work
//container.cloudKitContainerOptions?.databaseScope = .public
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "Market")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
}
guard let description = container.persistentStoreDescriptions.first else {
print("Can't set description")
fatalError("Error")
}
description.cloudKitContainerOptions?.databaseScope = .public

SwiftUI Preview canvas and Core Data

Preview canvas is is crashing but in simulator everything working fine. I assuming it related to #ObservedObject and #Fetchrequest...
tried solution for here Previewing ContentView with CoreData
doesn't work
import SwiftUI
import CoreData
struct TemplateEditor: View {
#Environment(\.managedObjectContext) var managedObjectContext
#FetchRequest(
entity: GlobalPlaceholders.entity(),
sortDescriptors: [
NSSortDescriptor(keyPath: \GlobalPlaceholders.category, ascending: false),
]
) var placeholders: FetchedResults<GlobalPlaceholders>
#ObservedObject var documentTemplate: Templates
#State private var documentTemplateDraft = DocumentTemplateDraft()
#Binding var editing: Bool
var body: some View {
VStack(){
HStack(){
cancelButton
Spacer()
saveButton
}.padding()
addButton
ForEach(placeholders) {placeholder in
Text(placeholder.name)
}
TextField("Title", text: $documentTemplateDraft.title)
TextField("Body", text: $documentTemplateDraft.body)
.padding()
.frame(width: 100, height:400)
Spacer()
}
...
}
struct TemplateEditor_Previews: PreviewProvider {
static var previews: some View {
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Templates")
request.sortDescriptors = [NSSortDescriptor(keyPath: \Templates.created, ascending: false)]
let documentTemplate = try! managedObjectContext.fetch(request).first as! Templates
return TemplateEditor(documentTemplate: documentTemplate, editing: .constant(true)).environment(\.managedObjectContext, managedObjectContext).environmentObject(documentTemplate)
}
}
Expected to generate preview
I'm not sure if your try line will work if there is no data.
let documentTemplate = try! managedObjectContext.fetch(request).first as! Templates
To get mine to work I created a test Item to use. Like this:
struct DetailView_Previews: PreviewProvider {
static var previews: some View {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
//Test data
let newEvent = Event.init(context: context)
newEvent.timestamp = Date()
return DetailView(event: newEvent).environment(\.managedObjectContext, context)
}
}
I've also noticed that I needed the .environment(.managedObjectContext, context) code in an earlier tabView that hosted the CoreData views or the preview would fail.
This answer seems to work in my recent project by replacing the default ContentView_Previews struct, though others are questioning whether it pulls persistent data. Credit goes to #ShadowDES - in the Master/Detail template project in Xcode Beta 7
I'm able to CRUD anything using Canvas (XCode Version 11.3 (11C29)) and it seems to run flawlessly.
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
return ContentView().environment(\.managedObjectContext, context)
}
}
#endif
What works for me:
I create all of my sample data in the preview property of my persistence controller, building off of the template generated by Xcode when starting a project with the following settings: Interface - SwiftUI, Lifecycle - SwiftUI App, Use Core Data, Host in CloudKit. I have posted the template here:
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
// ** Prepare all sample data for previews here ** //
for _ in 0..<10 {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
}
do {
try viewContext.save()
} catch {
// handle error for production
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "SwiftUISwiftAppCoreDataCloudKit")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// handle error for production
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
}
In my preview, I inject the persistence controller into the preview environment and for my view argument I use the registeredObjects.first(where:) method on the preview viewContext to pull the first object of the desired type:
struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView(item: PersistenceController.preview.container.viewContext.registeredObjects.first(where: { $0 is Item }) as! Item)
.environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}
Edited 11/15/21
Persistence
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
Seed().prepareData(for: viewContext)
return result
}()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "SwiftUISwiftAppCoreDataCloudKit")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// handle error for production
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
}
struct Seed {
func prepareData(for viewContext: NSManagedObjectContext) {
// ** Prepare all sample data for previews here ** //
for _ in 0..<10 {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()
}
do {
try viewContext.save()
} catch {
// handle error for production
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
Item Preview
struct ItemView_Previews: PreviewProvider {
static let persistence = PersistenceController.preview
static var item: Item = {
let context = persistence.container.viewContext
let item = Item(context: context)
item.timestamp = Date()
return item
}()
static var previews: some View {
ItemView(item: item)
.environment(\.managedObjectContext, persistence.container.viewContext)
}
}
So, if you put some code in an onAppear handler in the preview, it will run on boot. It even live updates as you type!
struct TemplateEditor_Previews: PreviewProvider {
static var previews: some View {
TemplateEditor().environment(\.managedObjectContext, AppDelegate.viewContext).onAppear {
let entity = GlobalPlaceholders(context: AppDelegate.viewContext)
entity.name = "abc123"
// Or create more, if you need more example data
try! AppDelegate.viewContext.save()
}
}
}
Note that I've wrapped up my viewContext in a static method on AppDelegate to make access a tiny bit less verbose and easier to remember:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
static var persistentContainer: NSPersistentContainer {
return (UIApplication.shared.delegate as! AppDelegate).persistentContainer
}
static var viewContext: NSManagedObjectContext {
return persistentContainer.viewContext
}
Works for SwiftUI 2 app using the App template
I also had the previews crash and none of the other solutions were suitable or worked for me.
What I did was rather than the following:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
return ContentView()
.environment(
\.managedObjectContext,
CoreDataManager.context
)
}
}
I fixed it with:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let context = CoreDataManager.context
/* Optional sample data can be inserted here */
return ContentView()
.environment(
\.managedObjectContext,
context
)
}
}
Where CoreDataManager is:
enum CoreDataManager {
static var context: NSManagedObjectContext {
persistentContainer.viewContext
}
static let persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyContainerName")
container.loadPersistentStores { description, error in
guard let error = error else { return }
fatalError("Core Data error: '\(error.localizedDescription)'.")
}
return container
}()
}
Not exactly sure why this helped, but now it works perfectly. Additionally you can add sample data to this context where I have marked with a comment.
This is my solution.
I don't want use CoreData in view. I want MVVM style.
So you need to mock Core data for display in Canvas view.
This is an example :
// View
struct MyView: View {
#ObservedObject var viewModel: PreviewViewModel
}
// View Model
final class MyViewModel: ObservableObject {
#Published var repository: RepositoryProtocol // CoreData
}
// Repository
protocol RepositoryProtocol { }
class Repository: RepositoryProtocol { ... }
class MockRepository: RepositoryProtocol { ... } // Create a Mock
// Init of your view
// If Canvas use mock
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
repository = MockRepository()
// else App use Repository
} else {
repository = Repository.shared
}
let viewModel = MyViewModel(repository:repository)
MyViewModel(viewModel: viewModel)
This worked for me. In the AppDelegate create a different preview context and fill it with objects.
lazy var persistentContainerPreview: NSPersistentContainer = {
let persistentContainer = NSPersistentContainer(name: "MyModel")
persistentContainer.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
}
})
let didCreateSampleData = UserDefaults.standard.bool(forKey: "didCreateSampleData")
if !didCreateSampleData {
let context = persistentContainer.viewContext
let recipe = Recipe(context: context)
recipe.title = "Soup 2"
recipe.difficultyName = "NOT TOO TRICKY"
recipe.difficultyValue = 1
recipe.heroImage = "dsfsdf"
recipe.ingredients = "meat"
recipe.method = "sdcsdsd"
recipe.published = Date()
recipe.recipeId = 1
recipe.servings = 4
recipe.tags = "sdfs"
recipe.totalTime = 100
recipe.totalTimeFormatted = "Less than 2 hours"
try! context.save()
}
return persistentContainer
}()
Then in your preview.
struct RecipeView_Previews: PreviewProvider {
static var previews: some View {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainerPreview.viewContext
let recipe = try! context.fetch(Recipe.fetchRequest()).first as! Recipe
RecipeView(recipe: recipe).environment(\.managedObjectContext, context)
}
}
One option is to NOT use Core Data in previews. This is helpful enough to see the UI of what I'm building but I'll still need to use Simulator to test the functionality.
#if !DEBUG
// Core Data related code e.g. #FetchRequest
#endif
What was suggested in Previewing ContentView with CoreData worked for me, Xcode Version 11.0 (11A419c) Mac OS 10.15 Beta (19A558d). My crash logs showed an index error,
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'
because there was no data there, so I had to handle this unique "preview" case and that got things working.
It crashes because it was instructed so in the PersistenceController:
struct PersistenceController {
...
static var preview: PersistenceController = {
...
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
...
}
So the actual reason can be seen in the crash report. Actually, XCode 12.4 shows a warning about checking the crash report; however, the report is too verbose for a newbie like me from web development. Thus it took me a while to find out the problem, so I hope this would save some time for others.
...and the problem in my case was a required attribute was not set while populating the core data model for previews.
The thing is you need to find out which line cause the crash.
Since the canvas doesn't show the detailed error, using OSLog and Console.app to debug would be a possible solution.
For example:
import os.log
struct YourView_Previews: PreviewProvider {
static var previews: some View {
os_log("[DEBUG]-\(#function)---1--")
let moc = PersistenceController.preview.container.viewContext
os_log("[DEBUG]-\(#function)---2--")
let item = Item.previewData(context: moc)
os_log("[DEBUG]-\(#function)---3--")
return YourView(item: item, now: Date())
.environment(\.managedObjectContext, moc)
}
}
Remember to use filter to better catch the debug message from Console.
After finding out which line cause the crash, you can further look into the line and continue the process until you find the culprit.
(In my case, I forgot to add UUID to the preview data which causing the canvas to crash.)

NSFetchedResultsController can't update the tableView swift4

I'm trying to make it work for last couple of days and can't get it working. Its something tiny detail obviously I can't seem to find.
Could you take a look and give me some insights about my code?
I'm trying to update the logView with app savings in the coredata.
Here's the entire code for ViewController and CoreData Handler.
/// fetch controller
lazy var fetchController: NSFetchedResultsController = { () -> NSFetchedResultsController<NSFetchRequestResult> in
let entity = NSEntityDescription.entity(forEntityName: "Logs", in: CoreDataHandler.sharedInstance.backgroundManagedObjectContext)
let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
fetchRequest.entity = entity
let nameDescriptor = NSSortDescriptor(key: "name", ascending: false)
fetchRequest.sortDescriptors = [nameDescriptor]
let fetchedController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: CoreDataHandler.sharedInstance.backgroundManagedObjectContext, sectionNameKeyPath: "duration", cacheName: nil)
fetchedController.delegate = self as? NSFetchedResultsControllerDelegate
return fetchedController
}()
override func viewDidLoad() {
title = "Week Log"
tableView.tableFooterView = UIView(frame: CGRect.zero)
tableView.separatorColor = UIColor.black
tableView.backgroundColor = UIColor.red
refreshView()
loadNormalState()
loadCoreDataEntities()
}
/**
Refresh the view, reload the tableView.
*/
func refreshView() {
loadCoreDataEntities()
tableView.reloadData()
}
/**
Load history entities from core data. (I'm printing on the console and
be able to see the the fetched data but I can't load it to tableView.)
*/
func loadCoreDataEntities() {
do {
try fetchController.performFetch()
} catch {
print("Error occurred while fetching")
}
}
import Foundation
import CoreData
class CoreDataHandler: NSObject {
/**
Creates a singleton object to be used across the whole app easier
- returns: CoreDataHandler
*/
class var sharedInstance: CoreDataHandler {
struct Static {
static var instance: CoreDataHandler = CoreDataHandler()
}
return Static.instance
}
lazy var backgroundManagedObjectContext: NSManagedObjectContext = {
let backgroundManagedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
let coordinator = self.persistentStoreCoordinator
backgroundManagedObjectContext.persistentStoreCoordinator = coordinator
return backgroundManagedObjectContext
}()
lazy var objectModel: NSManagedObjectModel = {
let modelPath = Bundle.main.url(forResource: "Model", withExtension: "momd")
let objectModel = NSManagedObjectModel(contentsOf: modelPath!)
return objectModel!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.objectModel)
// Get the paths to the SQLite file
let storeURL = self.applicationDocumentsDirectory().appendingPathComponent("Model.sqlite")
// Define the Core Data version migration options
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
// Attempt to load the persistent store
var error: NSError?
var failureReason = "There was an error creating or loading the application's saved data."
do {
try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: options)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject
dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return persistentStoreCoordinator
}()
func applicationDocumentsDirectory() -> NSURL {
return FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).last! as NSURL
}
func saveContext() {
do {
try backgroundManagedObjectContext.save()
} catch {
print("Error while saving the object context")
// Error occured while deleting objects
}
}
You have a data source delegate somewhere. That data source delegate tells the table view how many items there are, and what their contents is. How does it know how many items? That must be stored somewhere.
When the fetch controller is successful, it must modify the data that the data source delegate relies on in some way, and then call reloadData. Are you doing this? Are you doing anything that causes the data source delegate to change the number of items it reports?
And calling loadCoreDataEntities, immediately followed by reloadData, is nonsense. loadCoreDataEntities is asynchronous. By the time you call reloadData, it hasn't loaded any entities yet. realodData is called when loadCoreDataEntities has finished.

Resources