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.
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
// in the init code for my object
NSString *pathm = [[NSBundle mainBundle] pathForResource:@"mycoredb" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:pathm];
self.model = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
// in another method in the object
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [[self.model entitiesByName] objectForKey:@"Model_name"];
[request setEntity:entity];
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
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Model_name"];
no more "appears to be from a different NSManagedObjectModel than this context" error.
In my case it was a simple solution, I am using 4 contexts and I had to set their parent to the main context.
var mainManagedContext: NSManagedObjectContext {
return persistentContainer.viewContext
}
lazy var backgroundQueueContext: NSManagedObjectContext = {
let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
context.parent = mainManagedContext
return context
}()
lazy var mainQueueContext: NSManagedObjectContext = {
let context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
context.parent = mainManagedContext
return context
}()
lazy var alternativeContext: NSManagedObjectContext = {
let context = persistentContainer.newBackgroundContext()
return 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 same momd
file as the same model.
Make sure when you're referencing viewContext
it is as shared (same instance) of NSManagedObjectContext
and not initializing a new model instance from the file.
I hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With