I started to get the following error when launching my application on iOS 12 simulator. Did anybody face issue like this?
2018-08-11 21:17:44.440144+0300 CafeManager[4633:128874] [error] error: The fetch request's entity 0x600001f6e940 'TablesTable' appears to be from a different NSManagedObjectModel than this context's
I have global constant defined in AppDelegate:
let viewContext = AppDelegate.viewContext
And use it with NSFetchedResultsController for UITableView update, for example:
import UIKit
import CoreData
class HistoryTablesTableViewController: FetchedResultsTableViewController {
//MARK: variables
private var fetchedResultsController: NSFetchedResultsController<TablesTable>?
private var currentTable: TablesTable?
private var tableNameTextField: UITextField!
//MARK: system functions for view
override func viewDidLoad() {
super.viewDidLoad()
sideMenu()
addSyncObserver()
}
override func viewWillAppear(_ animated: Bool) {
updateGUI()
}
// MARK: IBOutlets
@IBOutlet weak var menuButton: UIBarButtonItem!
// MARK: side menu
private func sideMenu() {
if revealViewController() != nil {
menuButton.target = revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
revealViewController().rearViewRevealWidth = 260
view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
}
//MARK: functions for table update
private func updateGUI () {
let request : NSFetchRequest<TablesTable> = TablesTable.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "tableName", ascending: true, selector: #selector(NSString.localizedStandardCompare(_:)))]
fetchedResultsController = NSFetchedResultsController<TablesTable>(fetchRequest: request, managedObjectContext: viewContext, sectionNameKeyPath: nil, cacheName: nil)
try? fetchedResultsController?.performFetch()
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! HistoryTablesTableViewCell
if let tablesTable = fetchedResultsController?.object(at: indexPath) {
cell.tableNameLabel.text = tablesTable.tableName
cell.cellDelegate = self
cell.table = tablesTable
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath as IndexPath)
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
currentTable = fetchedResultsController?.object(at: indexPath)
performSegue(withIdentifier: "showTableSessions", sender: cell)
}
//MARK: prepare for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showTableSessions" {
if let tableSessionsTVC = segue.destination as? TableSessionsTableViewController {
tableSessionsTVC.title = self.currentTable!.tableName!
tableSessionsTVC.currentTable = self.currentTable!
}
}
}
}
// MARK: Delegates
extension HistoryTablesTableViewController: HistoryTablesTableViewCellDelegate {
func didPressTablesCellButton(table: TablesTable) {
currentTable = table
}
}
// Common extension for fetchedResultsController
extension HistoryTablesTableViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
return fetchedResultsController?.sections?.count ?? 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = fetchedResultsController?.sections, sections.count > 0 {
return sections[section].numberOfObjects
}
else {
return 0
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if let sections = fetchedResultsController?.sections, sections.count > 0 {
return sections[section].name
}
else {
return nil
}
}
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return fetchedResultsController?.sectionIndexTitles
}
override func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
return fetchedResultsController?.section(forSectionIndexTitle: title, at: index) ?? 0
}
}
// Observer to check that sync was performed to update GUI
extension HistoryTablesTableViewController {
private func addSyncObserver () {
NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: appDelegate.syncDidFinishNotification), object: nil, queue: nil) {
[weak self] notification in
DispatchQueue.main.async {
self?.updateGUI()
}
}
}
}
In the same time it looks like that app works, but had no chance to test everything properly yet.
I use CoreData, Seam3 framework.
I found the only one mention of this error on github, but do not see solution.
In my case it was a simple solution, I am using 4 contexts and I had to set their parent to the main context.
I ran into something similar when we created two instances of model even if they are read from the same
momd
file. My assumption was that if it's read from the same file, they should be the same model, but I guess something has changed internally that no longer treats two instances from read from the samemomd
file as the same model.Make sure when you're referencing
viewContext
it is as shared (same instance) ofNSManagedObjectContext
and not initializing a new model instance from the file.I hope this helps.
I had been getting this error with iOS 12 also. This is how I finally fixed it in my project. This is in Objective C, not Swift, but hopefully it will get you going in the right direction.
The code that produced this error looked like this
The issue has something to do with the entity. So I updated my code to reflect the example on this page: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/FetchingObjects.html
Here is how my code looks now
no more "appears to be from a different NSManagedObjectModel than this context" error.