Reputation: 638
I actively use StackOverflow almost daily for more than a year by now, but this is the first question I'm asking here. No other question grasp my exact problem. Solution to close ones doesn't work or doesn't really apply do my case.
I'm developing an iOS app with a share extension. The extension app save links into CoreData, the containing(main) app, exhibits a listing of this links saved utilizing NSFetchResultsController.
The main app is the Master-Detail template provided by Xcode with really small adaptation.
I've created a embedded framework to carry CoreData stuff and set an App Group to host the CoreData and share it between apps in the usual way.
The CoreData part is working fine: I can insert objects into the ContextObjectManager and whenever my main app becomes active I can query this inserted object there promptly.
The problem starts when MasterViewController fails to update tableView. I'm inferring the NSFetchedResultsController instance do not track CoreData changes when it happens outside the main app.
I try some approaches while listening to when app becomes active:
func becomeActive(notification: NSNotification) {
//Approach 1: Making sure to delete cache -- even though I do not have a persistent named cache file.
NSFetchedResultsController.deleteCacheWithName(nil)
//Approach 2: Making sure to reload tableView data.
self.tableView.reloadData()
}
It didn't have any effect.
self.fetchedResultsController.sections![0].numberOfObjects
it's always equal the number of exhibited cells. Then, if I share something new with the extension and then come back, this number doesn't change, but DataManager.getAllManagedObjectsFromEntity(Link.entityDescription()).objects.count
equals this quantity + 1.
And then, when I close the app and open it again, it's synced and number of exhibited cells = number of objects fetched = number of all managed objects got from entity.
It's it. Someone have any suggestions/solutions of what I need to do to sync up the fetched results?
NSFetchedResultsController instance in MasterViewController.swift
var fetchedResultsController: NSFetchedResultsController {
if _fetchedResultsController != nil {
return _fetchedResultsController!
}
let fetchRequest = NSFetchRequest()
// Edit the entity name as appropriate.
let entity = NSEntityDescription.entityForName("Link", inManagedObjectContext: DataAccess.shared.managedObjectContext)
fetchRequest.entity = entity
// Set the batch size to a suitable number.
fetchRequest.fetchBatchSize = 20
// Edit the sort key as appropriate.
let sortDescriptor = NSSortDescriptor(key: "title", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
/// Template original code
// let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: "Master")
/// My adaptation
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DataAccess.shared.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
aFetchedResultsController.delegate = self
_fetchedResultsController = aFetchedResultsController
do {
try _fetchedResultsController!.performFetch()
} catch {
abort()
}
return _fetchedResultsController!
}
func getAllManagedObjectsFromEntity(_:) at embedded framework's DataManager.swift
file
public class func getAllManagedObjectsFromEntity(entity: NSEntityDescription) -> (sucesso: Bool, objects: NSArray){
// let delegate = (UIApplication.sharedApplication()).delegate as! AppDelegate
let context:NSManagedObjectContext? = DataAccess.shared.managedObjectContext
let request:NSFetchRequest = NSFetchRequest()
request.entity = entity
var error:NSError?
var objects:NSArray?
do {
objects = try context?.executeFetchRequest(request)
} catch let error1 as NSError {
error = error1
objects = nil
}
if(error == nil){
return(true, objects!)
}else{
NSLog(error!.description)
return(false, objects!)
}
}
Upvotes: 7
Views: 1077
Reputation: 630
I had a similar problem, but, every time the application entered the foreground again, I made a new NSFetchedResultsController, performed my fetch, and then reloaded the UITableView and then it seemed all was up to date.
Upvotes: 0
Reputation: 13458
NSFetchedResultsController may have an NSFetchedResultsControllerDelegate attached.
You're already declaring that you implement NSFetchedResultsControllerDelegate:
aFetchedResultsController.delegate = self
so add the controllerDidChangeContent method, where you'll reload your table when this is called:
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{
self.tableView.reloadData
}
The NSFetchedResultsControllerDelegate also provides a dictionary on exactly what has changed, giving you very fine grained control.
Upvotes: 0