Posts

Post not yet marked as solved
3 Replies
1.4k Views
I am sharing my CoreData model between my iOS main app target and a new Share Extension target like this post:  This is working well for the most part except for one thing.  NSFetchedResultsController is not returning results when called from the Shared Extension. What is strange though is that if I do a plain NSFetchRequest in my Share Extension, I do get CoreData results returned that were originally saved from the main app...so I think Container setup as well as model must be being shared correctly via AppContainer. NSFetchedResultsControllerDelegate controllerDidChangeContent is never called. Any ideas or suggestions? import UIKit import MobileCoreServices class ShareViewController: UIViewController { private(set) lazy var resultsController: NSFetchedResultsController<Person> = createFetchedResultsController() override func viewDidLoad() { super.viewDidLoad() let fetchRequest = NSFetchRequest<Person>(entityName: "Person") fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)] do { /// this works! let persons = try CoreDataManager.shared.managedObjectContext.fetch(fetchRequest) print("Got \(persons.count) Persons") } catch { print("Fetch failed") } activateResultsController() } func createFetchedResultsController() -> NSFetchedResultsController<Person> { CoreDataManager.shared.container.viewContext.stalenessInterval = 0 CoreDataManager.shared.container.viewContext.refreshAllObjects() CoreDataManager.shared.container.viewContext.stalenessInterval = -1 let fetchRequest = NSFetchRequest<Person>(entityName: "Person") fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)] ////managedObjectContext: CoreDataManager.shared.managedObjectContext, let controller = NSFetchedResultsController( fetchRequest: fetchRequest, managedObjectContext: CoreDataManager.shared.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil ) controller.delegate = self return controller } private func activateResultsController() { do { try resultsController.performFetch() } catch { fatalError("Failed to fetch entities: \(error)") } } } // MARK: - Results Controller Delegate extension ShareViewController: NSFetchedResultsControllerDelegate { func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { guard let sections = resultsController.sections else { return } let section = sections[0] let rows = section.numberOfObjects print("rows=\(rows)") } } import UIKit import CoreData class CoreDataManager { static let shared = CoreDataManager() internal var container: NSPersistentContainer var managedObjectContext: NSManagedObjectContext { container.viewContext } init() { container = NSPersistentContainer(name: Constants.name) guard let storeDirectory = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first else { // We'll throw a fatalError() because we can't really proceed without storeDirectory fatalError(file: "Could not find .applicationSupportDirectory - exiting") } let storeURL = storeURL(for: "group.mygroup.testshareextensioncoredata", databaseName: "\(Constants.name)") let storeDescription = NSPersistentStoreDescription(url: storeURL) container.persistentStoreDescriptions = [storeDescription] container.loadPersistentStores(completionHandler: { storeDescription, error in if let error = error as NSError? { // We'll throw a fatalError() because we can't really proceed without loading the PersistentStore fatalError("loadPersistentStore failed \(error), \(error.userInfo)") } }) } // MARK: - Core Data Saving support func saveContext() { managedObjectContext.performAndWait { if managedObjectContext.hasChanges { do { try managedObjectContext.save() } catch { } } } } /// Returns a URL for the given app group and database pointing to the sqlite database. func storeURL(for appGroup: String, databaseName: String) -> URL { guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup) else { fatalError("Shared file container could not be created.") } return fileContainer.appendingPathComponent("\(databaseName).sqlite") } } internal extension CoreDataManager { enum Constants { static let name = "ShareExtensionCoreDataTest" } }
Posted
by tanzy_m.
Last updated
.