This problem has buzzed me quite a while. So far, I still haven't founded a good solution.
Currently, I have an entity with a Bool column named pinned. I use it as the sectionNameKeyPath for NSFetchedResultsController.
So, my UICollectionView will always have 1 sections (All pinned = true, or All pinned = false), or 2 sections (Some pinned = true, and some pinned = false)
When I toggle the pinned value from true to false, or false to true, I expect FRC shall fire a "move" callback. (Due to item has moved to a new section) This happen most of the time.
However, sometimes, randomly, instead of firing "move" callback, FRC will fire "update" callback.
When such incident happen, I will exam the content of fetchedResultsController.sections. Then, I will notice the entity item stays in wrong section.
My FRC looks pretty straightforward.
This is how I update the pinned column using background thread.
I am not really sure, whether this can caused by my background thread.
As, if I replace the backgroundContext with viewContext, I haven't observed the random problem so far.
But, even so, I am not confident to conclude using backgroundContext is the culprit to this problem.
The setup of my background thread is also pretty straightforward. I cannot see how it can went wrong.
I was wondering, have anyone of you encounter similar problem when trying to utilize sectionNameKeyPath or FRC? Do you know what? Do you have any workaround/ solution for that?
Thank you!
Currently, I have an entity with a Bool column named pinned. I use it as the sectionNameKeyPath for NSFetchedResultsController.
So, my UICollectionView will always have 1 sections (All pinned = true, or All pinned = false), or 2 sections (Some pinned = true, and some pinned = false)
When I toggle the pinned value from true to false, or false to true, I expect FRC shall fire a "move" callback. (Due to item has moved to a new section) This happen most of the time.
However, sometimes, randomly, instead of firing "move" callback, FRC will fire "update" callback.
When such incident happen, I will exam the content of fetchedResultsController.sections. Then, I will notice the entity item stays in wrong section.
My FRC looks pretty straightforward.
Code Block lazy var fetchedResultsController: NSFetchedResultsController<NSPlainNote> = { // Create a fetch request for the Quake entity sorted by time. let fetchRequest = NSFetchRequest<NSPlainNote>(entityName: "NSPlainNote") fetchRequest.sortDescriptors = [ NSSortDescriptor(key: "pinned", ascending: false) ] // Create a fetched results controller and set its fetch request, context, and delegate. let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: CoreDataStack.INSTANCE.persistentContainer.viewContext, sectionNameKeyPath: "pinned", cacheName: nil ) controller.delegate = fetchedResultsControllerDelegate // Perform the fetch. do { try controller.performFetch() } catch { fatalError("Unresolved error \(error)") } return controller }()
This is how I update the pinned column using background thread.
Code Block func updatePinned(_ objectID: NSManagedObjectID, _ pinned: Bool) { let coreDataStack = CoreDataStack.INSTANCE let backgroundContext = coreDataStack.backgroundContext backgroundContext.perform { let nsPlainNote = try! backgroundContext.existingObject(with: objectID) as! NSPlainNote nsPlainNote.pinned = pinned RepositoryUtils.saveContextIfPossible(backgroundContext) } }
I am not really sure, whether this can caused by my background thread.
As, if I replace the backgroundContext with viewContext, I haven't observed the random problem so far.
But, even so, I am not confident to conclude using backgroundContext is the culprit to this problem.
The setup of my background thread is also pretty straightforward. I cannot see how it can went wrong.
Code Block class CoreDataStack { public static let INSTANCE = CoreDataStack() private init() { } lazy var persistentContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: "***") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) // TODO: container.viewContext.automaticallyMergesChangesFromParent = true //container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy //container.viewContext.undoManager = nil //container.viewContext.shouldDeleteInaccessibleFaults = true return container }() lazy var backgroundContext: NSManagedObjectContext = { let backgroundContext = persistentContainer.newBackgroundContext() // TODO: //backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy //backgroundContext.undoManager = nil return backgroundContext }() }
I was wondering, have anyone of you encounter similar problem when trying to utilize sectionNameKeyPath or FRC? Do you know what? Do you have any workaround/ solution for that?
Thank you!